1 /* -*-C++-*- $NetBSD: hpcmenu.cpp,v 1.8 2001/05/17 01:50:35 enami Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <hpcmenu.h> 40 #include <hpcboot.h> 41 #include <res/resource.h> 42 #include <menu/window.h> 43 #include <menu/tabwindow.h> 44 #include <menu/rootwindow.h> 45 #include <menu/menu.h> 46 #include <machine/bootinfo.h> 47 #include <framebuffer.h> 48 #include <console.h> 49 50 HpcMenuInterface *HpcMenuInterface::_instance = 0; 51 52 HpcMenuInterface & 53 HpcMenuInterface::Instance() 54 { 55 if (!_instance) 56 _instance = new HpcMenuInterface(); 57 return *_instance; 58 } 59 60 void 61 HpcMenuInterface::Destroy() 62 { 63 if (_instance) 64 delete _instance; 65 } 66 67 HpcMenuInterface::HpcMenuInterface() 68 { 69 if (!load()) 70 _set_default_pref(); 71 _pref._version = HPCBOOT_VERSION; 72 _pref._size = sizeof(HpcMenuPreferences); 73 74 _cons_parameter = 0; 75 memset(_cons_hook, 0, sizeof(struct cons_hook_args) * 4); 76 memset(&_boot_hook, 0, sizeof(struct boot_hook_args)); 77 } 78 79 void 80 HpcMenuInterface::print(TCHAR *buf) 81 { 82 if (_console) 83 _console->print(buf); 84 } 85 86 void 87 HpcMenuInterface::get_options() 88 { 89 _main->get(); 90 _option->get(); 91 } 92 93 TCHAR * 94 HpcMenuInterface::dir(int i) 95 { 96 int res = IDS_DIR_RES(i); 97 if (!IDS_DIR_RES_VALID(res)) 98 return 0; 99 100 if (_pref.dir_user && res == IDS_DIR_USER_DEFINED) { 101 return _pref.dir_user_path; 102 } 103 104 TCHAR *s = reinterpret_cast <TCHAR *> 105 (LoadString(_root->_app._instance, res, 0, 0)); 106 107 return s; 108 } 109 110 int 111 HpcMenuInterface::dir_default() 112 { 113 return _pref.dir_user ? IDS_DIR_SEQ(IDS_DIR_USER_DEFINED) : 0; 114 } 115 116 void 117 HpcMenuInterface::_set_default_pref() 118 { 119 _pref._magic = HPCBOOT_MAGIC; 120 _pref.dir = 0; 121 _pref.dir_user = FALSE; 122 _pref.kernel_user = FALSE; 123 _pref.platid_hi = 0; 124 _pref.platid_lo = 0; 125 _pref.rootfs = 0; 126 wsprintf(_pref.rootfs_file, TEXT("miniroot.fs")); 127 _pref.boot_serial = FALSE; 128 _pref.boot_verbose = FALSE; 129 _pref.boot_single_user = FALSE; 130 _pref.boot_ask_for_name = FALSE; 131 _pref.boot_debugger = FALSE; 132 _pref.auto_boot = 0; 133 _pref.reverse_video = FALSE; 134 _pref.pause_before_boot = TRUE; 135 _pref.safety_message = TRUE; 136 #ifdef MIPS 137 _pref.serial_speed = 9600; // historical reason. 138 #else 139 _pref.serial_speed = 19200; 140 #endif 141 } 142 143 // 144 // load and save current menu status. 145 // 146 BOOL 147 HpcMenuInterface::load() 148 { 149 TCHAR path[MAX_PATH]; 150 151 if (!_find_pref_dir(path)) 152 return FALSE; 153 154 TCHAR filename[MAX_PATH]; 155 wsprintf(filename, TEXT("\\%s\\hpcboot.cnf"), path); 156 HANDLE file = CreateFile(filename, GENERIC_READ, 0, 0, OPEN_EXISTING, 157 FILE_ATTRIBUTE_NORMAL, 0); 158 if (file == INVALID_HANDLE_VALUE) 159 return FALSE; 160 161 DWORD cnt; 162 // read header. 163 if (!ReadFile(file, &_pref, 12, &cnt, 0)) 164 goto bad; 165 if (_pref._magic != HPCBOOT_MAGIC) 166 goto bad; 167 // read all. 168 SetFilePointer(file, 0, 0, FILE_BEGIN); 169 if (!ReadFile(file, &_pref, _pref._size, &cnt, 0)) 170 goto bad; 171 CloseHandle(file); 172 173 return TRUE; 174 bad: 175 CloseHandle(file); 176 return FALSE; 177 } 178 179 BOOL 180 HpcMenuInterface::save() 181 { 182 TCHAR path[MAX_PATH]; 183 184 if (_find_pref_dir(path)) { 185 TCHAR filename[MAX_PATH]; 186 wsprintf(filename, TEXT("\\%s\\hpcboot.cnf"), path); 187 HANDLE file = CreateFile(filename, GENERIC_WRITE, 0, 0, 188 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 189 DWORD cnt; 190 WriteFile(file, &_pref, _pref._size, &cnt, 0); 191 CloseHandle(file); 192 return cnt == _pref._size; 193 } 194 195 return FALSE; 196 } 197 198 // arguments for kernel. 199 int 200 HpcMenuInterface::setup_kernel_args(vaddr_t v, paddr_t p) 201 { 202 int argc = 0; 203 kaddr_t *argv = reinterpret_cast <kaddr_t *>(v); 204 char *loc = reinterpret_cast <char *> 205 (v + sizeof(char **) * MAX_KERNEL_ARGS); 206 paddr_t locp = p + sizeof(char **) * MAX_KERNEL_ARGS; 207 size_t len; 208 TCHAR *w; 209 210 #define SETOPT(c) \ 211 __BEGIN_MACRO \ 212 argv[argc++] = ptokv(locp); \ 213 *loc++ =(c); \ 214 *loc++ = '\0'; \ 215 locp += 2; \ 216 __END_MACRO 217 // 1st arg is kernel name. 218 // DPRINTF_SETUP(); if you want to use debug print, enable this line. 219 220 w = _pref.kernel_user_file; 221 argv[argc++] = ptokv(locp); 222 len = WideCharToMultiByte(CP_ACP, 0, w, wcslen(w), 0, 0, 0, 0); 223 WideCharToMultiByte(CP_ACP, 0, w, len, loc, len, 0, 0); 224 loc[len] = '\0'; 225 loc += len + 1; 226 locp += len + 1; 227 228 if (_pref.boot_serial) // serial console 229 SETOPT('h'); 230 if (_pref.boot_verbose) // boot verbosely 231 SETOPT('v'); 232 if (_pref.boot_single_user) // boot to single user 233 SETOPT('s'); 234 if (_pref.boot_ask_for_name) // ask for file name to boot from 235 SETOPT('a'); 236 if (_pref.boot_debugger) // break into the kernel debugger 237 SETOPT('d'); 238 239 // boot from 240 switch(_pref.rootfs) { 241 case 0: // wd0 242 break; 243 case 1: // sd0 244 argv[argc++] = ptokv(locp); 245 strncpy(loc, "b=sd0", 6); 246 loc += 6; 247 locp += 6; 248 break; 249 case 2: // memory disk 250 w = _pref.rootfs_file; 251 argv[argc++] = ptokv(locp); 252 strncpy(loc, "m=", 2); 253 loc += 2; 254 len = WideCharToMultiByte(CP_ACP, 0, w, wcslen(w), 0, 0, 0, 0); 255 WideCharToMultiByte(CP_ACP, 0, w, len, loc, len, 0, 0); 256 loc[len] = '\0'; 257 loc += len + 1; 258 locp += 2 + len + 1; 259 break; 260 case 3: // nfs 261 argv[argc++] = ptokv(locp); 262 strncpy(loc, "b=nfs", 6); 263 loc += 6; 264 locp += 6; 265 break; 266 } 267 268 return argc; 269 } 270 271 // kernel bootinfo. 272 void 273 HpcMenuInterface::setup_bootinfo(struct bootinfo &bi) 274 { 275 FrameBufferInfo fb(_pref.platid_hi, _pref.platid_lo); 276 TIME_ZONE_INFORMATION tz; 277 GetTimeZoneInformation(&tz); 278 279 memset(&bi, 0, sizeof(struct bootinfo)); 280 bi.length = sizeof(struct bootinfo); 281 bi.reserved = 0; 282 bi.magic = BOOTINFO_MAGIC; 283 bi.fb_addr = fb.addr(); 284 bi.fb_type = fb.type(); 285 bi.fb_line_bytes = fb.linebytes(); 286 bi.fb_width = fb.width(); 287 bi.fb_height = fb.height(); 288 bi.platid_cpu = _pref.platid_hi; 289 bi.platid_machine = _pref.platid_lo; 290 bi.timezone = tz.Bias; 291 } 292 293 // Progress bar 294 void 295 HpcMenuInterface::progress() 296 { 297 SendMessage(_root->_progress_bar->_window, PBM_STEPIT, 0, 0); 298 } 299 300 // Boot kernel. 301 void 302 HpcMenuInterface::boot() 303 { 304 struct support_status *tab = _unsupported; 305 u_int32_t cpu = _pref.platid_hi; 306 u_int32_t machine = _pref.platid_lo; 307 308 if (_pref.safety_message) 309 for (; tab->cpu; tab++) { 310 if (tab->cpu == cpu && tab->machine == machine) { 311 MessageBox(_root->_window, 312 tab->cause ? tab->cause : 313 L"not supported yet.", 314 TEXT("BOOT FAILED"), 0); 315 return; 316 } 317 } 318 319 if (_boot_hook.func) 320 _boot_hook.func(_boot_hook.arg); 321 } 322