Annotation of nono/vm/romemu_luna88k.cpp, revision 1.1.1.7

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.2   root        7: // LUNA88K の ROM エミュレーション
                      8: 
                      9: //             IODevice
                     10: //                |
1.1.1.5   root       11: //     +----------+---------------------+
                     12: //     v                                v
                     13: // ROMDevice                 LunaPROMEmuDeivce (ROM エミュレーションの共通部分)
                     14: //     |                                |
                     15: //     |                   +------------+----------------+
                     16: //     v                   v                             v
                     17: // PROMDevice      Luna1PROMEmuDevice          Luna88kPROMEmuDevice
                     18: // (実ROM)         (LUNA-I エミュレーション)   (LUNA88K エミュレーション)
1.1.1.2   root       19: 
                     20: #include "romemu_luna88k.h"
1.1.1.5   root       21: #include "iodevstream.h"
1.1.1.7 ! root       22: #include "lunafb.h"
1.1       root       23: #include "mainapp.h"
                     24: #include "memorystream.h"
1.1.1.7 ! root       25: #include "mk48t02.h"
1.1.1.5   root       26: #include "pio.h"
1.1       root       27: #include "ram.h"
1.1.1.5   root       28: #include "sysctlr.h"
1.1       root       29: 
                     30: // コンストラクタ
                     31: Luna88kPROMEmuDevice::Luna88kPROMEmuDevice()
                     32: {
                     33:        devaddr = baseaddr;
1.1.1.5   root       34: 
                     35:        // ROM の特定アドレスを読み出す人がいるかも知れないので、
                     36:        // サイズは実 ROM と同じにしておく。LUNA-I からの類推。
1.1.1.2   root       37:        devlen = 256 * 1024;
1.1.1.5   root       38:        romdata.reset(new uint8 [devlen]);
1.1.1.2   root       39: 
1.1.1.5   root       40:        // プロンプトを初期化。
1.1.1.7 ! root       41:        prompt = default_prompt;
1.1       root       42: }
                     43: 
                     44: // デストラクタ
                     45: Luna88kPROMEmuDevice::~Luna88kPROMEmuDevice()
                     46: {
                     47: }
                     48: 
                     49: bool
                     50: Luna88kPROMEmuDevice::Init()
                     51: {
1.1.1.5   root       52:        // 親クラス
                     53:        if (inherited::Init() == false) {
                     54:                return false;
                     55:        }
                     56: 
1.1.1.2   root       57:        MemoryStreamBE ms(romdata.get());
1.1       root       58: 
1.1.1.6   root       59:        // リセット時のブートページには ROM (これ) が見えている。
                     60:        // ROMIO_INIT へのアクセスでブートページを RAM に切り替えて、同時に RAM の
                     61:        // 0番地付近のベクタも作り直す。そのため、ここのベクタ1 以降 ($41000008〜)
                     62:        // をベクタとして参照することはないので、ベクタ0 の命令列がそのまま使い潰
                     63:        // してよい。というか2ワードでは 0番地から ROM まで飛べないので使わないと
                     64:        // 面倒くさい。一体どういう設計してんだ…。
                     65: 
                     66:                                                                        //      ; _ROM_START へジャンプ (ここは0番地)
                     67:        ms.Write32(0x5cc04100);                 //  or.u        r6, r0, #0x4100
                     68:        ms.Write32(0x58c6000c);                 //      or              r6, r6, #0x000c
                     69:        ms.Write32(0xf400c006);                 //      jmp             r6
1.1.1.5   root       70: 
1.1.1.6   root       71:                                                                        // _ROM_START: (ここは ROM)
1.1.1.5   root       72:                                                                        //      ; 元の PSR を r10 に保存しつつ
                     73:                                                                        //      ; 割り込み許可
                     74:        ms.Write32(0x81404020);                 //      ldcr    r10, psr
                     75:        ms.Write32(0xf04a8040);                 //      clr             r2, r10, 2<1>   ; IND,SFRZ
                     76:        ms.Write32(0x80028022);                 //      stcr    r2, psr
                     77:                                                                        //      ; r3 <- ROMIO_BASE
                     78:        ms.Write32(0x5c600000 |                 //      or.u    r3, r0, #ROMIO_BASE.Hi
                     79:                (ROMIO_BASE >> 16));            //
                     80:        ms.Write32(0x58630000 |                 //      or              r3, r0, #ROMIO_BASE.Lo
                     81:                (ROMIO_BASE & 0xffff));         //
                     82:                                                                        //      ; ROMIO_INIT を読み出す
                     83:        ms.Write32(0x14430000);                 //      ld              r2, r3, #+INIT
                     84:                                                                        //      ; 起動先があれば GO
                     85:        ms.Write32(0xe9a20005);                 //      bcnd    ne0, r2, _go
                     86:                                                                        // _prompt:
                     87:                                                                        //      ; 疑似 STOP でキー入力を待つ
                     88:        ms.Write32(0xc8000001);                 //      bsr             _stop
                     89:                                                                        //      ; この時点で r1 = _stop
                     90:                                                                        // _stop:
                     91:        ms.Write32(0xf400c001);                 //      jmp             r1
                     92:                                                                        // _back:
                     93:        ms.Write32(0x14430000 |                 //      ld              r2, r3, #+ENTRY
                     94:                (ROMIO_ENTRY - ROMIO_BASE));//
                     95:                                                                        //      ; 起動先がなければループ
                     96:        ms.Write32(0xe842fffd);                 //      bcnd    eq0, r2, _prompt
                     97:                                                                        //      ; 起動先があれば後始末して
                     98:        ms.Write32(0x14030000 |                 // _go:
                     99:                (ROMIO_CLOSE - ROMIO_BASE));//  ld              r0, r3, #+CLOSE
                    100:                                                                        //      ; 割り込み禁止に戻す
                    101:        ms.Write32(0x800a802a);                 //      stcr    r10, psr
                    102:                                                                        //      ; ジャンプ
                    103:        ms.Write32(0xf400c002);                 //      jmp             r2
                    104: 
                    105:        // ここから割り込みハンドラ。割り込みは SIO のみ許可にしてある。
                    106:        // キーボード割り込みが上がったら KEYIN をコールして _back に戻る。
                    107:        ms.SetPtr(&romdata[0x200]);
                    108:        ms.Write32(0x14030000 |                 //      ld              r0, r3, #+KEYIN
                    109:                (ROMIO_KEYIN - ROMIO_BASE));//
                    110:                                                                        //      ; 戻ったところの jmp を抜ける
                    111:        ms.Write32(0x60210004);                 //      addu    r1, r1, #4
                    112:        ms.Write32(0xf400fc00);                 //      rte
1.1       root      113: 
                    114:        return true;
                    115: }
                    116: 
1.1.1.6   root      117: void
                    118: Luna88kPROMEmuDevice::ResetHard()
                    119: {
                    120:        inherited::ResetHard();
                    121: 
                    122:        b_entrypoint = 0;
                    123: }
                    124: 
1.1.1.5   root      125: // 起動時の処理を行う。
                    126: // 次段実行ファイルの読み込みに成功すればそのエントリポイントを返す。
                    127: // そうでなければ 0 を返すので、プロンプトに処理を移すこと。
                    128: uint32
                    129: Luna88kPROMEmuDevice::ROM_Init()
1.1       root      130: {
1.1.1.5   root      131:        IODeviceStream rs(gRAM.get());
                    132:        uint32 entry;
1.1       root      133: 
1.1.1.5   root      134:        // デバイスの初期化 (親クラス)
                    135:        InitDevice();
1.1.1.6   root      136: 
1.1.1.5   root      137:        // 割り込みマスクで SIO だけ許可
                    138:        gInterrupt->Write32(0x65000000, 0x40000000);
1.1       root      139: 
1.1.1.5   root      140:        rs.SetAddr(0);
                    141:        // ベクタテーブルを rte で埋めておく
                    142:        for (int i = 0; i < 512 * 2; i++) {
                    143:                rs.Write32(0xf400fc00 /* rte */);
                    144:        }
                    145:        // +$08: 割り込みベクタ
                    146:        rs.Write32(8, 0xc00003fe);              // br   $00001000
                    147: 
                    148:        // 割り込みトランポリン (0x1000)
                    149:        // ベクタテーブルは各2ワードしかないのに、0 番地付近にあるベクタテーブル
                    150:        // から2ワードでは ROM まで飛べない。一体どういう設計してんだ…。
                    151:        rs.SetAddr(0x1000);
                    152:        rs.Write32(0x5cc04100);                 // or.u r6, r0, #0x4100
                    153:        rs.Write32(0x58c60200);                 // or   r6, r6, #0x0200
                    154:        rs.Write32(0xf400c006);                 // jmp  r6
1.1.1.2   root      155: 
1.1.1.5   root      156:        // ROM の機能テーブル
                    157:        // 0x00001100 からあるようだ
                    158:        // 0x0000110c GETC()
                    159:        // 0x00001110 PUTC(c)
                    160:        // 0x00001114 ビットマッププレーンの有効状態が入っている。
                    161:        //  bit0: plane0 有効
                    162:        //  bit1..7: plane1..7 有効
                    163:        rs.SetAddr(0x110c);
                    164:        rs.Write32(0x00001300);
                    165:        rs.Write32(0x00001400);
                    166:        rs.Write32(0x00000001);
                    167: 
                    168:        // ROM GETC エミュレータ
                    169:        rs.SetAddr(0x1300);
                    170:        rs.Write32(0xfc000c00);                 // internal inst getc
                    171:        rs.Write32(0xf400c001);                 // jmp r1
1.1.1.2   root      172: 
1.1.1.5   root      173:        // ROM PUTC エミュレータ
                    174:        rs.SetAddr(0x1400);
                    175:        rs.Write32(0xfc001000);                 // internal inst putc
                    176:        rs.Write32(0xf400c001);                 // jmp r1
                    177: 
                    178:        // スクリーンを初期化
                    179:        InitScreen("LUNA88K");
                    180: 
                    181:        entry = 0;
                    182: 
                    183:        // 表示環境が整ったところで NVRAM を照合
                    184:        if (VerifyNVRAM() == false) {
1.1.1.7 ! root      185:                // PROM 1.20 は初期化するかどうか確認してくるけど、とりあえず。
1.1.1.5   root      186:                InitNVRAM();
                    187:                text.Print("** NVRAM Initialized.\n");
                    188:                text.Print("\n");
                    189:                // NVRAM をクリアしたら DIPSW によらずプロンプトに降りる
                    190:                goto done;
                    191:        }
                    192: 
                    193:        // DIPSW#1-1 が UP なら自動起動、DOWN なら ROM モニタ起動なので、
                    194:        // これを真似する。
                    195:        if ((gPIO0->GetDIPSW1() & 1)) {
                    196:                if (gMainApp.host_file) {
                    197:                        // ホストのファイルを読み込んでエントリポイントアドレスを
                    198:                        // この Read アクセスの読み出し値として返す。
                    199:                        // エラーがあればエラーメッセージは呼び出し先側で表示してある。
                    200:                        entry = LoadHostFile();
                    201:                } else {
                    202:                        // NVRAM の設定に従ってブート先を探す。
                    203:                        errmsg.clear();
                    204: 
                    205:                        bootinfo_t bootinfo;
                    206:                        GetNVRAM(bootinfo);
                    207:                        entry = LoadGuestFile(bootinfo);
                    208:                        if (entry == 0) {
                    209:                                text.Print("** %s\n", errmsg.c_str());
                    210:                        }
                    211:                }
                    212:        }
                    213: 
                    214:        // ここまでタイトルなどを Print してはいるが、実際の画面更新は
                    215:        // ConsoleUpdate() を呼ぶまで行われないことを利用(悪用?)して、
                    216:        // ここでエラーなくブートプログラムに制御を渡せる場合には何も表示せずに
                    217:        // ゲストに処理を移す。意図して或いは意図せずプロンプトに降りる場合だけ
                    218:        // ConsoleUpdate を呼ぶことでタイトルを含めて画面を表示する。
                    219:  done:
                    220:        if (entry == 0) {
1.1.1.7 ! root      221:                ClearPrompt();
1.1.1.5   root      222:                ConsoleUpdate();
                    223:        }
                    224: 
                    225:        return entry;
                    226: }
                    227: 
                    228: // ROM 処理。エントリポイントを返す。
                    229: uint32
                    230: Luna88kPROMEmuDevice::ROM_Entry()
                    231: {
                    232:        if (b_entrypoint != 0) {
                    233:                return b_entrypoint;
1.1.1.2   root      234:        } else {
1.1.1.5   root      235:                return 0;
1.1.1.2   root      236:        }
                    237: }
                    238: 
1.1.1.7 ! root      239: void
        !           240: Luna88kPROMEmuDevice::GetChar(char asciicode)
        !           241: {
        !           242:        if (prompt_idx == 0) {
        !           243:                // 行入力モード (画面更新もしてある)
        !           244:                inherited::GetChar(asciicode);
        !           245:        } else {
        !           246:                // 0 以外ならノンブロッキングモード
        !           247: 
        !           248:                // 入力されたキーを表示
        !           249:                text.SetAttr(TA::Normal);
        !           250:                if (' ' <= asciicode && asciicode < 0x7f) {
        !           251:                        text.Putc(asciicode);
        !           252:                }
        !           253: 
        !           254:                switch (prompt_idx) {
        !           255:                 case PROMPT_NVRAM_UPDATE:
        !           256:                        CommandNvramUpdate2(asciicode);
        !           257:                        break;
        !           258: 
        !           259:                 case PROMPT_NVRAM_NEW:
        !           260:                        CommandNvramNew2(asciicode);
        !           261:                        break;
        !           262: 
        !           263:                 case PROMPT_NVRAM_INIT:
        !           264:                        CommandNvramInit2(asciicode);
        !           265:                        break;
        !           266:                }
        !           267: 
        !           268:                // プロンプトを戻す
        !           269:                prompt = default_prompt;
        !           270:                prompt_idx = 0;
        !           271:                prompt_y = text.GetY();
        !           272: 
        !           273:                // こっちは画面更新をする必要がある
        !           274:                ConsoleUpdate();
        !           275:        }
        !           276: }
        !           277: 
1.1.1.5   root      278: // 入力コマンド処理 (入力行が揃ったところで呼ばれる)。
                    279: //
                    280: // b                                   現在のパラメータで起動
                    281: // b ...                               パラメータを指定して起動
                    282: // nvram                               全パラメータを表示
                    283: // nvram [<name>]              name のみ表示?
                    284: // nvram <name> <val>  値を設定
                    285: // nvram - <name>              削除
                    286: // nvram--                             NVRAM 初期化
                    287: 
                    288: void
                    289: Luna88kPROMEmuDevice::Command()
1.1.1.2   root      290: {
1.1.1.5   root      291:        std::vector<char> buf(inputbuf.length() + 1);
                    292:        std::vector<std::string> arg;
1.1.1.2   root      293: 
1.1.1.5   root      294:        // 1ワードごとに分解
                    295:        strcpy(&buf[0], inputbuf.c_str());
                    296:        char *p = &buf[0];
1.1.1.6   root      297:        for (char *ap; (ap = strsep(&p, " ")) != NULL; ) {
                    298:                if (*ap != '\0') {
                    299:                        arg.push_back(std::string(ap));
1.1.1.5   root      300:                }
                    301:        }
                    302:        if (loglevel >= 1) {
                    303:                for (int i = 0; i < arg.size(); i++) {
                    304:                        putmsgn("arg[%d]=|%s|", i, arg[i].c_str());
                    305:                }
                    306:        }
1.1.1.2   root      307: 
1.1.1.5   root      308:        // 空行
                    309:        if (arg.size() == 0) {
                    310:                return;
                    311:        }
                    312: 
                    313:        // 1ワード目がコマンド
                    314:        if (arg[0] == "h") {
1.1.1.7 ! root      315:                CommandH(arg);
1.1.1.5   root      316:                return;
                    317:        }
                    318:        if (arg[0] == "b") {
                    319:                CommandB(arg);
                    320:                return;
                    321:        }
                    322:        if (arg[0] == "nvram") {
                    323:                CommandNvram(arg);
                    324:                return;
1.1.1.2   root      325:        }
1.1.1.5   root      326: 
                    327:        text.Print("** Unknown command: %s\n", arg[0].c_str());
1.1.1.2   root      328: }
                    329: 
1.1.1.7 ! root      330: // "h" コマンド
        !           331: // 引数なしなら、全体のヘルプメッセージ。
        !           332: // 引数ありなら、個別のヘルプメッセージ。
        !           333: void
        !           334: Luna88kPROMEmuDevice::CommandH(const std::vector<std::string>& arg)
        !           335: {
        !           336:        if (arg.size() < 2) {
        !           337:                // ヘルプメッセージ
        !           338:  mainhelp:
        !           339:                text.Print(
        !           340: "         *** Help Message ***\n"
        !           341: "  b      : load and execute program\n"
        !           342: "  h      : show this message\n"
        !           343: "  nvram  : show/set nvram parameters\n"
        !           344:                );
        !           345:                return;
        !           346:        }
        !           347: 
        !           348:        const std::string& key = arg[1];
        !           349:        if (key == "nvram") {
        !           350:                text.Print(
        !           351: "         *** Help Message ***\n"
        !           352: " nvram [<symbol>]       : show\n"
        !           353: " nvram <symbol> <value> : set\n"
        !           354: " nvram - <symbol>       : delete\n"
        !           355: " nvram --               : initialize\n"
        !           356:                );
        !           357:                return;
        !           358:        } else {
        !           359:                goto mainhelp;
        !           360:        }
        !           361: }
        !           362: 
1.1.1.5   root      363: // "b" コマンド
                    364: // 引数なしなら NVRAM の情報に従ってプログラムをロードして実行。
                    365: // 引数ありのほうは未実装。
                    366: void
                    367: Luna88kPROMEmuDevice::CommandB(const std::vector<std::string>& arg)
1.1       root      368: {
1.1.1.5   root      369:        errmsg.clear();
1.1       root      370: 
1.1.1.5   root      371:        // XXX とりあえず boot を起動するだけ
                    372:        bootinfo_t bootinfo;
                    373:        GetNVRAM(bootinfo);
                    374:        b_entrypoint = LoadGuestFile(bootinfo);
                    375:        if (b_entrypoint == 0) {
                    376:                text.Print("** %s\n", errmsg.c_str());
1.1       root      377:        }
1.1.1.5   root      378: }
1.1       root      379: 
1.1.1.5   root      380: // "bh" コマンド (勝手に拡張)
                    381: // -A オプションで指定されたホストプログラムをロードして実行。
                    382: void
                    383: Luna88kPROMEmuDevice::CommandBH()
                    384: {
                    385:        // 指定されてたら読み込む
                    386:        if (gMainApp.host_file == NULL) {
                    387:                text.Print("** Cannot loaded; host program is not specified.\n");
                    388:                return;
1.1.1.2   root      389:        }
1.1.1.5   root      390:        b_entrypoint = LoadHostFile();
1.1.1.2   root      391: }
                    392: 
1.1.1.7 ! root      393: // "nvram" コマンド
        !           394: // nvram             .. 全表示
        !           395: // nvram <key>       .. 表示
        !           396: // nvram <key> <val> .. 追加/更新
        !           397: // nvram - <key>     .. 削除
        !           398: // nvram --          .. 初期化
1.1.1.5   root      399: void
                    400: Luna88kPROMEmuDevice::CommandNvram(const std::vector<std::string>& arg)
1.1.1.2   root      401: {
1.1.1.7 ! root      402:        switch (arg.size()) {
        !           403:         case 1:
        !           404:                // 引数なし
        !           405:                CommandNvramShowAll();
        !           406:                break;
        !           407:         case 2:
        !           408:                // 引数1つ
        !           409:                if (arg[1] == "--") {
        !           410:                        CommandNvramInit();
        !           411:                } else {
        !           412:                        CommandNvramShow(arg);
        !           413:                }
        !           414:                break;
        !           415:         case 3:
        !           416:                // 引数2つ
        !           417:                if (arg[1] == "-") {
        !           418:                        CommandNvramDelete(arg);
        !           419:                } else {
        !           420:                        CommandNvramUpdate(arg);
        !           421:                }
        !           422:                break;
        !           423:         default:
        !           424:                text.Print("** Syntax error\n");
        !           425:        }
        !           426: }
        !           427: 
        !           428: // NVRAM は 32バイトを1エントリとする。
        !           429: // [0] はヘッダに相当し、フォーマットは別記。
        !           430: // [1] 以降が key (16バイト)、val(16バイト) の並び。こんな感じ。
        !           431: //
        !           432: // 00000020  62 6f 6f 74 5f 64 65 76 69 63 65 00 00 00 00 00 |boot_device.....|
        !           433: // 00000030  73 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |sd..............|
        !           434: //
        !           435: // key, val とも '\0' で終端もしくは16文字で終端のようだ。
        !           436: // val に17文字を設定しようとすると怒られる。
        !           437: // key が "" ならこのエントリは空きで val は無視、
        !           438: // 空きエントリは無視して次へ (FAT のディレクトリエントリみたいな感じ)。
        !           439: // val が "" は有効。
        !           440: //
        !           441: // オフセット 0x540 から始まるエントリが最後で、これ以上追加しようとすると
        !           442: // "nvram set error: no area" (PROM 1.20) と言われる。
        !           443: // LUNA88K にはないが LUNA-I では 0x560 にぽつんと ENADDR があったので、
        !           444: // その辺りとの互換性だろうか。
        !           445: 
        !           446: // NVRAM 全項目表示
        !           447: void
        !           448: Luna88kPROMEmuDevice::CommandNvramShowAll()
        !           449: {
        !           450:        putmsg(1, "nvram ShowAll");
        !           451:        for (uint32 offset = 0x20; offset < 0x560; offset += 0x20) {
        !           452:                std::string key = nvram->PeekString(offset);
        !           453:                if (key.empty()) {
        !           454:                        continue;
        !           455:                }
        !           456:                std::string val = nvram->PeekString(offset + 16);
        !           457:                text.Print("%-15s : %s\n", key.c_str(), val.c_str());
        !           458:        }
        !           459: }
        !           460: 
        !           461: // NVRAM 指定項目を表示
        !           462: void
        !           463: Luna88kPROMEmuDevice::CommandNvramShow(const std::vector<std::string>& arg)
        !           464: {
        !           465:        assert(arg.size() >= 2);
        !           466:        const std::string& key = arg[1];
        !           467: 
        !           468:        putmsg(1, "nvram Show |%s|", key.c_str());
        !           469:        uint32 offset = FindNVRAM(key);
        !           470:        if (offset > 0) {
        !           471:                std::string val = nvram->PeekString(offset + 16);
        !           472:                text.Print("%-15s : %s\n", key.c_str(), val.c_str());
        !           473:        } else {
        !           474:                text.Print("** Not found\n");
        !           475:        }
        !           476: }
        !           477: 
        !           478: // NVRAM 項目を追加/更新
        !           479: void
        !           480: Luna88kPROMEmuDevice::CommandNvramUpdate(const std::vector<std::string>& arg)
        !           481: {
        !           482:        // キーがあれば更新、なければ追加。
        !           483:        // いずれも事前にプロンプトで確認する。
        !           484: 
        !           485:        assert(arg.size() >= 3);
        !           486:        nvram_key = arg[1];
        !           487:        nvram_val = arg[2];
        !           488:        putmsg(1, "nvram Update |%s|%s|", nvram_key.c_str(), nvram_val.c_str());
        !           489: 
        !           490:        if (nvram_key.size() > 16) {
        !           491:                text.Print("** Key too long\n");
        !           492:                return;
        !           493:        }
        !           494:        if (nvram_val.size() > 16) {
        !           495:                text.Print("** Val too long\n");
        !           496:                return;
        !           497:        }
        !           498: 
        !           499:        nvram_offset = FindNVRAM(nvram_key);
        !           500:        if (nvram_offset > 0) {
        !           501:                // キーがすでにあれば更新。
        !           502:                // Update2() に申し送りするのは nvram_offset と nvram_val のみでいい。
        !           503: 
        !           504:                std::string oldval = nvram->PeekString(nvram_offset + 16);
        !           505:                prompt = string_format("Update %s : \"%s\" -> \"%s\" (Y/[N]):",
        !           506:                        nvram_key.c_str(), oldval.c_str(), nvram_val.c_str());
        !           507:                prompt_idx = PROMPT_NVRAM_UPDATE;
        !           508:        } else {
        !           509:                // キーがなければ追加
        !           510:                // New2() に申し送りするのは nvram_offset, nvram_key, nvram_val の3つ。
        !           511: 
        !           512:                // 先に空き領域をチェックしている
        !           513:                nvram_offset = FindNVRAM("");
        !           514:                if (nvram_offset == 0) {
        !           515:                        text.Print("** No area available\n");
        !           516:                        return;
        !           517:                }
        !           518: 
        !           519:                prompt = string_format("Set new %s : \"%s\" (Y/[N]):",
        !           520:                        nvram_key.c_str(), nvram_val.c_str());
        !           521:                prompt_idx = PROMPT_NVRAM_NEW;
        !           522:        }
        !           523: 
        !           524:        // 入力待ちの状態で戻る
        !           525:        // (prompt_idx != 0 なのでキー入力後に指定の関数へ飛んで続きを実行する)
        !           526: }
        !           527: 
        !           528: // NVRAM 項目を更新 (キー入力後)
        !           529: void
        !           530: Luna88kPROMEmuDevice::CommandNvramUpdate2(char asciicode)
        !           531: {
        !           532:        assert(prompt_idx == PROMPT_NVRAM_UPDATE);
        !           533:        assert(nvram_offset > 0);
        !           534:        assert(nvram_val.size() <= 16);
        !           535: 
        !           536:        text.CRLF();
        !           537: 
        !           538:        if (asciicode != 'y' && asciicode != 'Y') {
        !           539:                text.Print("** Not updated\n");
        !           540:                return;
        !           541:        }
        !           542: 
        !           543:        if (nvram->WriteString(nvram_offset + 16, nvram_val) == false) {
        !           544:                text.Print("** Write error\n");
        !           545:                return;
        !           546:        }
        !           547:        WriteNVRAMCsum();
        !           548: 
        !           549:        text.Print("Updated\n");
        !           550: }
        !           551: 
        !           552: // NVRAM 項目を追加 (キー入力後)
        !           553: void
        !           554: Luna88kPROMEmuDevice::CommandNvramNew2(char asciicode)
        !           555: {
        !           556:        assert(prompt_idx == PROMPT_NVRAM_NEW);
        !           557:        assert(nvram_offset > 0);
        !           558:        assert(!nvram_key.empty());
        !           559:        assert(nvram_key.size() <= 16);
        !           560:        assert(nvram_val.size() <= 16);
        !           561: 
        !           562:        text.CRLF();
        !           563: 
        !           564:        if (asciicode != 'y' && asciicode != 'Y') {
        !           565:                text.Print("** Not added\n");
        !           566:                return;
        !           567:        }
        !           568: 
        !           569:        if (nvram->WriteString(nvram_offset, nvram_key) == false
        !           570:         || nvram->WriteString(nvram_offset + 16, nvram_val) == false) {
        !           571:                text.Print("** Write error\n");
        !           572:                return;
        !           573:        }
        !           574:        WriteNVRAMCsum();
        !           575: 
        !           576:        text.Print("Added\n");
1.1.1.2   root      577: }
                    578: 
1.1.1.7 ! root      579: // NVRAM 項目削除
        !           580: //
        !           581: // 削除する時は確認がないらしい… (PROM 1.20)
        !           582: // 成功しても何も言わないらしい… (PROM 1.20)
        !           583: // 追加削除に比べてなんか雑じゃない?
        !           584: void
        !           585: Luna88kPROMEmuDevice::CommandNvramDelete(const std::vector<std::string>& arg)
        !           586: {
        !           587:        assert(arg.size() >= 3);
        !           588:        assert(arg[1] == "-");
        !           589:        const std::string& key = arg[2];
        !           590:        putmsg(1, "nvram Delete |%s|", key.c_str());
        !           591: 
        !           592:        if (key.size() > 16) {
        !           593:                text.Print("** key too long\n");
        !           594:                return;
        !           595:        }
        !           596: 
        !           597:        uint32 offset = FindNVRAM(key);
        !           598:        if (offset == 0) {
        !           599:                text.Print("** Not found\n");
        !           600:                return;
        !           601:        }
        !           602: 
        !           603:        // キーを消せば削除になる (値のほうは消してないようだ)
        !           604:        nvram->WriteString(offset, "");
        !           605:        WriteNVRAMCsum();
        !           606: }
        !           607: 
        !           608: // NVRAM から key を探してそのエントリのオフセットを返す。
        !           609: // key == "" なら空きエントリを探す。
        !           610: // 見付からなければ 0 を返す (オフセット 0 はパラメータには使わないため)
        !           611: uint32
        !           612: Luna88kPROMEmuDevice::FindNVRAM(const std::string& key) const
1.1.1.2   root      613: {
1.1.1.7 ! root      614:        for (uint32 offset = 0x20; offset < 0x560; offset += 0x20) {
        !           615:                std::string k = nvram->PeekString(offset);
        !           616:                if (k == key) {
        !           617:                        return offset;
        !           618:                }
        !           619:                // XXX 同じキーが複数あったらどうなるか
        !           620:        }
1.1.1.2   root      621:        return 0;
                    622: }
                    623: 
1.1.1.7 ! root      624: // NVRAM 初期化
1.1.1.5   root      625: void
1.1.1.7 ! root      626: Luna88kPROMEmuDevice::CommandNvramInit()
1.1.1.2   root      627: {
1.1.1.7 ! root      628:        putmsg(1, "nvram Init");
        !           629: 
        !           630:        prompt = "Initialize (Y/[N]):";
        !           631:        prompt_idx = PROMPT_NVRAM_INIT;
        !           632: 
        !           633:        // 入力待ちの状態で戻る
1.1.1.2   root      634: }
                    635: 
1.1.1.7 ! root      636: // NVRAM 初期化 (キー入力後)
        !           637: void
        !           638: Luna88kPROMEmuDevice::CommandNvramInit2(char asciicode)
1.1.1.2   root      639: {
1.1.1.7 ! root      640:        assert(prompt_idx == PROMPT_NVRAM_INIT);
        !           641: 
        !           642:        text.CRLF();
        !           643: 
        !           644:        if (asciicode != 'y' && asciicode != 'Y') {
        !           645:                text.Print("** Not initialized\n");
        !           646:                return;
        !           647:        }
        !           648: 
        !           649:        InitNVRAM();
        !           650:        text.Print("** Initialized\n");
1.1       root      651: }
                    652: 
1.1.1.5   root      653: // NVRAM を初期化する
                    654: bool
                    655: Luna88kPROMEmuDevice::InitNVRAM()
1.1       root      656: {
1.1.1.7 ! root      657:        nvram->ClearAll();
        !           658: 
        !           659:        nvram->WriteString(0x0004, "<nv>");
        !           660:        nvram->WriteString(0x0020, "boot_device");
        !           661:        nvram->WriteString(0x0030, "sd");
        !           662:        nvram->WriteString(0x0040, "boot_spec");
        !           663:        nvram->WriteString(0x0050, "0");
        !           664:        nvram->WriteString(0x0060, "boot_unit");
        !           665:        nvram->WriteString(0x0070, "0");
        !           666:        nvram->WriteString(0x0080, "boot_partition");
        !           667:        nvram->WriteString(0x0090, "0");
        !           668:        nvram->WriteString(0x00a0, "boot_filename");
        !           669:        nvram->WriteString(0x00b0, "vmunix");
        !           670:        nvram->WriteString(0x00c0, "main_mem_check");
        !           671:        nvram->WriteString(0x00d0, "1");
        !           672:        nvram->WriteString(0x00e0, "3port_mem_check");
        !           673:        nvram->WriteString(0x00f0, "1");
        !           674: 
        !           675:        // チェックサム再計算
        !           676:        WriteNVRAMCsum();
        !           677: 
        !           678:        return true;
1.1.1.5   root      679: }
1.1       root      680: 
1.1.1.5   root      681: // NVRAM のブート設定を bootinfo に取得する。
                    682: void
                    683: Luna88kPROMEmuDevice::GetNVRAM(bootinfo_t& bootinfo)
                    684: {
1.1.1.7 ! root      685:        // dkunit (装置番号) はたぶん boot_unit (0..)
        !           686:        // dkpart (パーティション) は boot_partition (0..)
        !           687:        // dkfile (ファイル名) は boot_filename
        !           688:        // sd 以外のデバイスは未対応
        !           689:        bootinfo.dkunit = nvram->Peek(0x0070) - '0';
        !           690:        bootinfo.dkpart = nvram->Peek(0x0090) - '0';
        !           691:        bootinfo.dkfile = nvram->PeekString(0x00b0);
        !           692:        putmsg(1, "%s unit=%d", __func__, bootinfo.dkunit);
        !           693:        putmsg(1, "%s part=%c", __func__, bootinfo.dkpart + 'a');
        !           694:        putmsg(1, "%s file=|%s|", __func__, bootinfo.dkfile.c_str());
1.1       root      695: }

unix.superglobalmegacorp.com

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