1*bd926f64Such /* -*-C++-*- $NetBSD: hpcmenu.cpp,v 1.6 2001/04/24 19:27:59 uch Exp $ */ 29173eae7Such 39173eae7Such /*- 49173eae7Such * Copyright (c) 2001 The NetBSD Foundation, Inc. 59173eae7Such * All rights reserved. 69173eae7Such * 79173eae7Such * This code is derived from software contributed to The NetBSD Foundation 89173eae7Such * by UCHIYAMA Yasushi. 99173eae7Such * 109173eae7Such * Redistribution and use in source and binary forms, with or without 119173eae7Such * modification, are permitted provided that the following conditions 129173eae7Such * are met: 139173eae7Such * 1. Redistributions of source code must retain the above copyright 149173eae7Such * notice, this list of conditions and the following disclaimer. 159173eae7Such * 2. Redistributions in binary form must reproduce the above copyright 169173eae7Such * notice, this list of conditions and the following disclaimer in the 179173eae7Such * documentation and/or other materials provided with the distribution. 189173eae7Such * 3. All advertising materials mentioning features or use of this software 199173eae7Such * must display the following acknowledgement: 209173eae7Such * This product includes software developed by the NetBSD 219173eae7Such * Foundation, Inc. and its contributors. 229173eae7Such * 4. Neither the name of The NetBSD Foundation nor the names of its 239173eae7Such * contributors may be used to endorse or promote products derived 249173eae7Such * from this software without specific prior written permission. 259173eae7Such * 269173eae7Such * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 279173eae7Such * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 289173eae7Such * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 299173eae7Such * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 309173eae7Such * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 319173eae7Such * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 329173eae7Such * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 339173eae7Such * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 349173eae7Such * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 359173eae7Such * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 369173eae7Such * POSSIBILITY OF SUCH DAMAGE. 379173eae7Such */ 389173eae7Such 399173eae7Such #include <hpcmenu.h> 409173eae7Such #include <hpcboot.h> 419173eae7Such #include <res/resource.h> 429173eae7Such #include <menu/window.h> 439173eae7Such #include <menu/tabwindow.h> 449173eae7Such #include <menu/rootwindow.h> 45*bd926f64Such #include <menu/menu.h> 469173eae7Such #include <machine/bootinfo.h> 479173eae7Such #include <framebuffer.h> 489173eae7Such #include <console.h> 499173eae7Such 509173eae7Such HpcMenuInterface *HpcMenuInterface::_instance = 0; 519173eae7Such 529173eae7Such HpcMenuInterface & 53a7876b44Such HpcMenuInterface::Instance() 549173eae7Such { 559173eae7Such if (!_instance) 569173eae7Such _instance = new HpcMenuInterface(); 579173eae7Such return *_instance; 589173eae7Such } 599173eae7Such 609173eae7Such void 61a7876b44Such HpcMenuInterface::Destroy() 629173eae7Such { 639173eae7Such if (_instance) 649173eae7Such delete _instance; 659173eae7Such } 669173eae7Such 67*bd926f64Such HpcMenuInterface::HpcMenuInterface() 68*bd926f64Such { 69*bd926f64Such if (!load()) 70*bd926f64Such _set_default_pref(); 71*bd926f64Such _pref._version = HPCBOOT_VERSION; 72*bd926f64Such _pref._size = sizeof(HpcMenuPreferences); 73*bd926f64Such 74*bd926f64Such _cons_parameter = 0; 75*bd926f64Such memset(_cons_hook, 0, sizeof(struct cons_hook_args) * 4); 76*bd926f64Such memset(&_boot_hook, 0, sizeof(struct boot_hook_args)); 77*bd926f64Such } 78*bd926f64Such 799173eae7Such void 809173eae7Such HpcMenuInterface::print(TCHAR *buf) 819173eae7Such { 829173eae7Such if (_console) 839173eae7Such _console->print(buf); 849173eae7Such } 859173eae7Such 869173eae7Such void 87a7876b44Such HpcMenuInterface::get_options() 889173eae7Such { 899173eae7Such _main->get(); 909173eae7Such _option->get(); 919173eae7Such } 929173eae7Such 939173eae7Such TCHAR * 949173eae7Such HpcMenuInterface::dir(int i) 959173eae7Such { 969173eae7Such int res = IDS_DIR_RES(i); 979173eae7Such if (!IDS_DIR_RES_VALID(res)) 989173eae7Such return 0; 999173eae7Such 1009173eae7Such if (_pref.dir_user && res == IDS_DIR_USER_DEFINED) { 1019173eae7Such return _pref.dir_user_path; 1029173eae7Such } 1039173eae7Such 1049173eae7Such TCHAR *s = reinterpret_cast <TCHAR *> 1059173eae7Such (LoadString(_root->_app._instance, res, 0, 0)); 1069173eae7Such 1079173eae7Such return s; 1089173eae7Such } 1099173eae7Such 1109173eae7Such int 111a7876b44Such HpcMenuInterface::dir_default() 1129173eae7Such { 1139173eae7Such return _pref.dir_user ? IDS_DIR_SEQ(IDS_DIR_USER_DEFINED) : 0; 1149173eae7Such } 1159173eae7Such 116*bd926f64Such void 117*bd926f64Such HpcMenuInterface::_set_default_pref() 118*bd926f64Such { 119*bd926f64Such _pref._magic = HPCBOOT_MAGIC; 120*bd926f64Such _pref.dir = 0; 121*bd926f64Such _pref.dir_user = FALSE; 122*bd926f64Such _pref.kernel_user = FALSE; 123*bd926f64Such _pref.platid_hi = 0; 124*bd926f64Such _pref.platid_lo = 0; 125*bd926f64Such _pref.rootfs = 0; 126*bd926f64Such wsprintf(_pref.rootfs_file, TEXT("miniroot.fs")); 127*bd926f64Such _pref.boot_serial = FALSE; 128*bd926f64Such _pref.boot_verbose = FALSE; 129*bd926f64Such _pref.boot_single_user = FALSE; 130*bd926f64Such _pref.boot_ask_for_name = FALSE; 131*bd926f64Such _pref.auto_boot = 0; 132*bd926f64Such _pref.reverse_video = FALSE; 133*bd926f64Such _pref.pause_before_boot = TRUE; 134*bd926f64Such _pref.safety_message = TRUE; 135*bd926f64Such #ifdef MIPS 136*bd926f64Such _pref.serial_speed = 9600; // historical reason. 137*bd926f64Such #else 138*bd926f64Such _pref.serial_speed = 19200; 139*bd926f64Such #endif 140*bd926f64Such } 141*bd926f64Such 142*bd926f64Such // 143*bd926f64Such // load and save current menu status. 144*bd926f64Such // 1459173eae7Such BOOL 146a7876b44Such HpcMenuInterface::load() 1479173eae7Such { 1489173eae7Such TCHAR path[MAX_PATH]; 1499173eae7Such 1509173eae7Such if (!_find_pref_dir(path)) 1519173eae7Such return FALSE; 1529173eae7Such 1539173eae7Such TCHAR filename[MAX_PATH]; 1549173eae7Such wsprintf(filename, TEXT("\\%s\\hpcboot.cnf"), path); 1559173eae7Such HANDLE file = CreateFile(filename, GENERIC_READ, 0, 0, OPEN_EXISTING, 1569173eae7Such FILE_ATTRIBUTE_NORMAL, 0); 1579173eae7Such if (file == INVALID_HANDLE_VALUE) 1589173eae7Such return FALSE; 1599173eae7Such 1609173eae7Such DWORD cnt; 1619173eae7Such // read header. 1629173eae7Such if (!ReadFile(file, &_pref, 12, &cnt, 0)) 1639173eae7Such goto bad; 1649173eae7Such if (_pref._magic != HPCBOOT_MAGIC) 1659173eae7Such goto bad; 1669173eae7Such // read all. 1679173eae7Such SetFilePointer(file, 0, 0, FILE_BEGIN); 1689173eae7Such if (!ReadFile(file, &_pref, _pref._size, &cnt, 0)) 1699173eae7Such goto bad; 1709173eae7Such CloseHandle(file); 1719173eae7Such 1729173eae7Such return TRUE; 1739173eae7Such bad: 1749173eae7Such CloseHandle(file); 1759173eae7Such return FALSE; 1769173eae7Such } 1779173eae7Such 1789173eae7Such BOOL 179a7876b44Such HpcMenuInterface::save() 1809173eae7Such { 1819173eae7Such TCHAR path[MAX_PATH]; 1829173eae7Such 1839173eae7Such if (_find_pref_dir(path)) { 1849173eae7Such TCHAR filename[MAX_PATH]; 1859173eae7Such wsprintf(filename, TEXT("\\%s\\hpcboot.cnf"), path); 1869173eae7Such HANDLE file = CreateFile(filename, GENERIC_WRITE, 0, 0, 1879173eae7Such CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 1889173eae7Such 0); 1899173eae7Such DWORD cnt; 1909173eae7Such WriteFile(file, &_pref, _pref._size, &cnt, 0); 1919173eae7Such CloseHandle(file); 1929173eae7Such return cnt == _pref._size; 1939173eae7Such } 1949173eae7Such 1959173eae7Such return FALSE; 1969173eae7Such } 1979173eae7Such 1989173eae7Such // arguments for kernel. 1999173eae7Such int 2009173eae7Such HpcMenuInterface::setup_kernel_args(vaddr_t v, paddr_t p) 2019173eae7Such { 2029173eae7Such int argc = 0; 2039173eae7Such kaddr_t *argv = reinterpret_cast <kaddr_t *>(v); 2049173eae7Such char *loc = reinterpret_cast <char *> 2059173eae7Such (v + sizeof(char **) * MAX_KERNEL_ARGS); 2069173eae7Such paddr_t locp = p + sizeof(char **) * MAX_KERNEL_ARGS; 2079173eae7Such size_t len; 2089173eae7Such TCHAR *w; 2099173eae7Such 2109173eae7Such #define SETOPT(c) \ 2119173eae7Such __BEGIN_MACRO \ 2129173eae7Such argv[argc++] = ptokv(locp); \ 2139173eae7Such *loc++ =(c); \ 2149173eae7Such *loc++ = '\0'; \ 2159173eae7Such locp += 2; \ 2169173eae7Such __END_MACRO 2179173eae7Such // 1st arg is kernel name. 2189173eae7Such // DPRINTF_SETUP(); if you want to use debug print, enable this line. 2199173eae7Such 2209173eae7Such w = _pref.kernel_user_file; 2219173eae7Such argv[argc++] = ptokv(locp); 2229173eae7Such len = WideCharToMultiByte(CP_ACP, 0, w, wcslen(w), 0, 0, 0, 0); 2239173eae7Such WideCharToMultiByte(CP_ACP, 0, w, len, loc, len, 0, 0); 2249173eae7Such loc[len] = '\0'; 2259173eae7Such loc += len + 1; 2269173eae7Such locp += len + 1; 2279173eae7Such 2289173eae7Such if (_pref.boot_serial) // serial console 2299173eae7Such SETOPT('h'); 2309173eae7Such if (_pref.boot_verbose) // boot verbosely 2319173eae7Such SETOPT('v'); 2329173eae7Such if (_pref.boot_single_user) // boot to single user 2339173eae7Such SETOPT('s'); 2349173eae7Such if (_pref.boot_ask_for_name) // ask for file name to boot from 2359173eae7Such SETOPT('a'); 2369173eae7Such 2379173eae7Such // boot from 2389173eae7Such switch(_pref.rootfs) { 2399173eae7Such case 0: // wd0 2409173eae7Such break; 2419173eae7Such case 1: // sd0 242df98929eSuch argv[argc++] = ptokv(locp); 243df98929eSuch strncpy(loc, "b=sd0", 6); 244df98929eSuch loc += 6; 245df98929eSuch locp += 6; 2469173eae7Such break; 2479173eae7Such case 2: // memory disk 2489173eae7Such w = _pref.rootfs_file; 2499173eae7Such argv[argc++] = ptokv(locp); 2509173eae7Such strncpy(loc, "m=", 2); 2519173eae7Such loc += 2; 2529173eae7Such len = WideCharToMultiByte(CP_ACP, 0, w, wcslen(w), 0, 0, 0, 0); 2539173eae7Such WideCharToMultiByte(CP_ACP, 0, w, len, loc, len, 0, 0); 2549173eae7Such loc[len] = '\0'; 2559173eae7Such loc += len + 1; 2569173eae7Such locp += 2 + len + 1; 2579173eae7Such break; 2589173eae7Such case 3: // nfs 2599173eae7Such argv[argc++] = ptokv(locp); 2609173eae7Such strncpy(loc, "b=nfs", 6); 2619173eae7Such loc += 6; 2629173eae7Such locp += 6; 2639173eae7Such break; 2649173eae7Such } 2659173eae7Such 2669173eae7Such return argc; 2679173eae7Such } 2689173eae7Such 2699173eae7Such // kernel bootinfo. 2709173eae7Such void 2719173eae7Such HpcMenuInterface::setup_bootinfo(struct bootinfo &bi) 2729173eae7Such { 2739173eae7Such FrameBufferInfo fb(_pref.platid_hi, _pref.platid_lo); 2749173eae7Such TIME_ZONE_INFORMATION tz; 2759173eae7Such GetTimeZoneInformation(&tz); 2769173eae7Such 2779173eae7Such memset(&bi, 0, sizeof(struct bootinfo)); 2789173eae7Such bi.length = sizeof(struct bootinfo); 2799173eae7Such bi.reserved = 0; 2809173eae7Such bi.magic = BOOTINFO_MAGIC; 2819173eae7Such bi.fb_addr = fb.addr(); 2829173eae7Such bi.fb_type = fb.type(); 2839173eae7Such bi.fb_line_bytes = fb.linebytes(); 2849173eae7Such bi.fb_width = fb.width(); 2859173eae7Such bi.fb_height = fb.height(); 2869173eae7Such bi.platid_cpu = _pref.platid_hi; 2879173eae7Such bi.platid_machine = _pref.platid_lo; 2889173eae7Such bi.timezone = tz.Bias; 2899173eae7Such } 2909173eae7Such 2919173eae7Such // Progress bar 2929173eae7Such void 293a7876b44Such HpcMenuInterface::progress() 2949173eae7Such { 2959173eae7Such SendMessage(_root->_progress_bar->_window, PBM_STEPIT, 0, 0); 2969173eae7Such } 297a7876b44Such 298*bd926f64Such // Boot kernel. 299a7876b44Such void 300a7876b44Such HpcMenuInterface::boot() 301a7876b44Such { 302a7876b44Such struct support_status *tab = _unsupported; 303a7876b44Such u_int32_t cpu = _pref.platid_hi; 304a7876b44Such u_int32_t machine = _pref.platid_lo; 305a7876b44Such 306a7876b44Such if (_pref.safety_message) 307a7876b44Such for (; tab->cpu; tab++) { 308a7876b44Such if (tab->cpu == cpu && tab->machine == machine) { 309a7876b44Such MessageBox(_root->_window, 310a7876b44Such tab->cause ? tab->cause : 311a7876b44Such L"not supported yet.", 312a7876b44Such TEXT("BOOT FAILED"), 0); 313a7876b44Such return; 314a7876b44Such } 315a7876b44Such } 316a7876b44Such 317a7876b44Such if (_boot_hook.func) 318*bd926f64Such _boot_hook.func(_boot_hook.arg); 319a7876b44Such } 320