xref: /netbsd-src/sys/arch/hpc/stand/hpcboot/hpcmenu.cpp (revision bd926f64c671a91f9d55422aa2553d9dc36a54c5)
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