1*569b7f92Snonaka /* -*-C++-*- $NetBSD: hpcmenu.cpp,v 1.19 2010/04/06 16:20:27 nonaka Exp $ */
29173eae7Such
39173eae7Such /*-
4b5f1c496Such * Copyright (c) 2001, 2004 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 *
199173eae7Such * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209173eae7Such * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219173eae7Such * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229173eae7Such * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239173eae7Such * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249173eae7Such * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259173eae7Such * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269173eae7Such * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279173eae7Such * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289173eae7Such * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299173eae7Such * POSSIBILITY OF SUCH DAMAGE.
309173eae7Such */
319173eae7Such
329173eae7Such #include <hpcmenu.h>
339173eae7Such #include <hpcboot.h>
349173eae7Such #include <res/resource.h>
359173eae7Such #include <menu/window.h>
369173eae7Such #include <menu/tabwindow.h>
379173eae7Such #include <menu/rootwindow.h>
38bd926f64Such #include <menu/menu.h>
399173eae7Such #include <machine/bootinfo.h>
409173eae7Such #include <framebuffer.h>
419173eae7Such #include <console.h>
42d1f348c0Such #include <string.h>
439173eae7Such
449173eae7Such HpcMenuInterface *HpcMenuInterface::_instance = 0;
459173eae7Such
469173eae7Such HpcMenuInterface &
Instance()47a7876b44Such HpcMenuInterface::Instance()
489173eae7Such {
4932b30275Such
509173eae7Such if (!_instance)
519173eae7Such _instance = new HpcMenuInterface();
529173eae7Such return *_instance;
539173eae7Such }
549173eae7Such
559173eae7Such void
Destroy()56a7876b44Such HpcMenuInterface::Destroy()
579173eae7Such {
5832b30275Such
599173eae7Such if (_instance)
609173eae7Such delete _instance;
619173eae7Such }
629173eae7Such
HpcMenuInterface()63bd926f64Such HpcMenuInterface::HpcMenuInterface()
64bd926f64Such {
6532b30275Such
66bd926f64Such if (!load())
67bd926f64Such _set_default_pref();
68bd926f64Such _pref._version = HPCBOOT_VERSION;
69bd926f64Such _pref._size = sizeof(HpcMenuPreferences);
70bd926f64Such
71bd926f64Such _cons_parameter = 0;
72bd926f64Such memset(_cons_hook, 0, sizeof(struct cons_hook_args) * 4);
73bd926f64Such memset(&_boot_hook, 0, sizeof(struct boot_hook_args));
74bd926f64Such }
75bd926f64Such
769173eae7Such void
print(TCHAR * buf)779173eae7Such HpcMenuInterface::print(TCHAR *buf)
789173eae7Such {
7932b30275Such
809173eae7Such if (_console)
819173eae7Such _console->print(buf);
829173eae7Such }
839173eae7Such
849173eae7Such void
get_options()85a7876b44Such HpcMenuInterface::get_options()
869173eae7Such {
8732b30275Such
889173eae7Such _main->get();
899173eae7Such _option->get();
909173eae7Such }
919173eae7Such
929173eae7Such TCHAR *
dir(int i)939173eae7Such HpcMenuInterface::dir(int i)
949173eae7Such {
959173eae7Such int res = IDS_DIR_RES(i);
9632b30275Such
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
dir_default()111a7876b44Such HpcMenuInterface::dir_default()
1129173eae7Such {
11332b30275Such
1149173eae7Such return _pref.dir_user ? IDS_DIR_SEQ(IDS_DIR_USER_DEFINED) : 0;
1159173eae7Such }
1169173eae7Such
117bd926f64Such void
_set_default_pref()118bd926f64Such HpcMenuInterface::_set_default_pref()
119bd926f64Such {
12032b30275Such
121bd926f64Such _pref._magic = HPCBOOT_MAGIC;
122bd926f64Such _pref.dir = 0;
123bd926f64Such _pref.dir_user = FALSE;
124bd926f64Such _pref.kernel_user = FALSE;
125bd926f64Such _pref.platid_hi = 0;
126bd926f64Such _pref.platid_lo = 0;
127bd926f64Such _pref.rootfs = 0;
128bd926f64Such wsprintf(_pref.rootfs_file, TEXT("miniroot.fs"));
129bd926f64Such _pref.boot_serial = FALSE;
130bd926f64Such _pref.boot_verbose = FALSE;
131bd926f64Such _pref.boot_single_user = FALSE;
132bd926f64Such _pref.boot_ask_for_name = FALSE;
133c7a624dcSenami _pref.boot_debugger = FALSE;
134d1f348c0Such wsprintf(_pref.boot_extra, TEXT(""));
135bd926f64Such _pref.auto_boot = 0;
136bd926f64Such _pref.reverse_video = FALSE;
137bd926f64Such _pref.pause_before_boot = TRUE;
138bd926f64Such _pref.safety_message = TRUE;
139bd926f64Such #ifdef MIPS
140bd926f64Such _pref.serial_speed = 9600; // historical reason.
141bd926f64Such #else
142bd926f64Such _pref.serial_speed = 19200;
143bd926f64Such #endif
144bd926f64Such }
145bd926f64Such
146bd926f64Such //
147bd926f64Such // load and save current menu status.
148bd926f64Such //
1499173eae7Such BOOL
load()150a7876b44Such HpcMenuInterface::load()
1519173eae7Such {
1529173eae7Such TCHAR path[MAX_PATH];
1539173eae7Such
1549173eae7Such if (!_find_pref_dir(path))
1559173eae7Such return FALSE;
1569173eae7Such
1579173eae7Such TCHAR filename[MAX_PATH];
1589173eae7Such wsprintf(filename, TEXT("\\%s\\hpcboot.cnf"), path);
1599173eae7Such HANDLE file = CreateFile(filename, GENERIC_READ, 0, 0, OPEN_EXISTING,
1609173eae7Such FILE_ATTRIBUTE_NORMAL, 0);
1619173eae7Such if (file == INVALID_HANDLE_VALUE)
1629173eae7Such return FALSE;
1639173eae7Such
1649173eae7Such DWORD cnt;
1659173eae7Such // read header.
1669173eae7Such if (!ReadFile(file, &_pref, 12, &cnt, 0))
1679173eae7Such goto bad;
1689173eae7Such if (_pref._magic != HPCBOOT_MAGIC)
1699173eae7Such goto bad;
1709173eae7Such // read all.
1719173eae7Such SetFilePointer(file, 0, 0, FILE_BEGIN);
1729173eae7Such if (!ReadFile(file, &_pref, _pref._size, &cnt, 0))
1739173eae7Such goto bad;
1749173eae7Such CloseHandle(file);
1759173eae7Such
1769173eae7Such return TRUE;
1779173eae7Such bad:
1789173eae7Such CloseHandle(file);
1799173eae7Such return FALSE;
1809173eae7Such }
1819173eae7Such
1829173eae7Such BOOL
save()183a7876b44Such HpcMenuInterface::save()
1849173eae7Such {
1859173eae7Such TCHAR path[MAX_PATH];
1869173eae7Such
1879173eae7Such if (_find_pref_dir(path)) {
1889173eae7Such TCHAR filename[MAX_PATH];
1899173eae7Such wsprintf(filename, TEXT("\\%s\\hpcboot.cnf"), path);
1909173eae7Such HANDLE file = CreateFile(filename, GENERIC_WRITE, 0, 0,
191fae3e8e7Such CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1929173eae7Such DWORD cnt;
1939173eae7Such WriteFile(file, &_pref, _pref._size, &cnt, 0);
1949173eae7Such CloseHandle(file);
1959173eae7Such return cnt == _pref._size;
1969173eae7Such }
1979173eae7Such
1989173eae7Such return FALSE;
1999173eae7Such }
2009173eae7Such
2019173eae7Such // arguments for kernel.
2029173eae7Such int
setup_kernel_args(vaddr_t v,paddr_t p,size_t sz)203d1f348c0Such HpcMenuInterface::setup_kernel_args(vaddr_t v, paddr_t p, size_t sz)
2049173eae7Such {
2059173eae7Such int argc = 0;
2069173eae7Such kaddr_t *argv = reinterpret_cast <kaddr_t *>(v);
2079173eae7Such char *loc = reinterpret_cast <char *>
2089173eae7Such (v + sizeof(char **) * MAX_KERNEL_ARGS);
2099173eae7Such paddr_t locp = p + sizeof(char **) * MAX_KERNEL_ARGS;
2109173eae7Such size_t len;
2119173eae7Such TCHAR *w;
212d1f348c0Such char *ptr;
2139173eae7Such
2149173eae7Such #define SETOPT(c) \
2159173eae7Such __BEGIN_MACRO \
2169173eae7Such argv[argc++] = ptokv(locp); \
2179173eae7Such *loc++ =(c); \
2189173eae7Such *loc++ = '\0'; \
2199173eae7Such locp += 2; \
2209173eae7Such __END_MACRO
2219173eae7Such // 1st arg is kernel name.
222d1f348c0Such // DPRINTF_SETUP(); //if you want to use debug print, enable this line.
2239173eae7Such
2249173eae7Such w = _pref.kernel_user_file;
2259173eae7Such argv[argc++] = ptokv(locp);
2269173eae7Such len = WideCharToMultiByte(CP_ACP, 0, w, wcslen(w), 0, 0, 0, 0);
2279173eae7Such WideCharToMultiByte(CP_ACP, 0, w, len, loc, len, 0, 0);
2289173eae7Such loc[len] = '\0';
2299173eae7Such loc += len + 1;
2309173eae7Such locp += len + 1;
2319173eae7Such
2329173eae7Such if (_pref.boot_serial) // serial console
2339173eae7Such SETOPT('h');
2349173eae7Such if (_pref.boot_verbose) // boot verbosely
2359173eae7Such SETOPT('v');
2369173eae7Such if (_pref.boot_single_user) // boot to single user
2379173eae7Such SETOPT('s');
2389173eae7Such if (_pref.boot_ask_for_name) // ask for file name to boot from
2399173eae7Such SETOPT('a');
240c7a624dcSenami if (_pref.boot_debugger) // break into the kernel debugger
241c7a624dcSenami SETOPT('d');
2429173eae7Such
2439173eae7Such // boot from
2449173eae7Such switch(_pref.rootfs) {
2459173eae7Such case 0: // wd0
2469173eae7Such break;
2479173eae7Such case 1: // sd0
248df98929eSuch argv[argc++] = ptokv(locp);
249df98929eSuch strncpy(loc, "b=sd0", 6);
250df98929eSuch loc += 6;
251df98929eSuch locp += 6;
2529173eae7Such break;
2539173eae7Such case 2: // memory disk
2549173eae7Such w = _pref.rootfs_file;
2559173eae7Such argv[argc++] = ptokv(locp);
2569173eae7Such strncpy(loc, "m=", 2);
2579173eae7Such loc += 2;
2589173eae7Such len = WideCharToMultiByte(CP_ACP, 0, w, wcslen(w), 0, 0, 0, 0);
2599173eae7Such WideCharToMultiByte(CP_ACP, 0, w, len, loc, len, 0, 0);
2609173eae7Such loc[len] = '\0';
2619173eae7Such loc += len + 1;
2629173eae7Such locp += 2 + len + 1;
2639173eae7Such break;
2649173eae7Such case 3: // nfs
2659173eae7Such argv[argc++] = ptokv(locp);
2669173eae7Such strncpy(loc, "b=nfs", 6);
2679173eae7Such loc += 6;
2689173eae7Such locp += 6;
2699173eae7Such break;
270*569b7f92Snonaka case 4: // dk0
271*569b7f92Snonaka argv[argc++] = ptokv(locp);
272*569b7f92Snonaka strncpy(loc, "b=dk0", 6);
273*569b7f92Snonaka loc += 6;
274*569b7f92Snonaka locp += 6;
275*569b7f92Snonaka break;
276*569b7f92Snonaka case 5: // ld0
277*569b7f92Snonaka argv[argc++] = ptokv(locp);
278*569b7f92Snonaka strncpy(loc, "b=ld0", 6);
279*569b7f92Snonaka loc += 6;
280*569b7f92Snonaka locp += 6;
281*569b7f92Snonaka break;
2829173eae7Such }
2839173eae7Such
284d1f348c0Such // Extra kernel options. (Option tab window)
285d1f348c0Such w = _pref.boot_extra;
286d1f348c0Such len = WideCharToMultiByte(CP_ACP, 0, w, wcslen(w), 0, 0, 0, 0);
287d1f348c0Such
288d1f348c0Such if ((ptr = (char *)malloc(len)) == NULL) {
289d1f348c0Such MessageBox(_root->_window,
290545bd4c3Suwe L"Can't allocate memory for extra kernel options.",
291545bd4c3Suwe TEXT("WARNING"),
292545bd4c3Suwe MB_ICONWARNING | MB_OK);
2938c941b84Suwe UpdateWindow(_root->_window);
294d1f348c0Such
295d1f348c0Such return argc;
296d1f348c0Such }
297d1f348c0Such WideCharToMultiByte(CP_ACP, 0, w, len, ptr, len, 0, 0);
298d1f348c0Such ptr[len]='\0';
299d1f348c0Such
300d1f348c0Such while (*ptr == ' ' || *ptr == '\t')
301d1f348c0Such ptr++;
302d1f348c0Such while (*ptr != '\0') {
303d1f348c0Such len = strcspn(ptr, " \t");
304d1f348c0Such if (len == 0)
305d1f348c0Such len = strlen(ptr);
306d1f348c0Such
307d1f348c0Such if (argc == MAX_KERNEL_ARGS || locp + len + 1 > p + sz) {
308d1f348c0Such MessageBox(_root->_window,
309d1f348c0Such L"Too many extra kernel options.",
310545bd4c3Suwe TEXT("WARNING"),
311545bd4c3Suwe MB_ICONWARNING | MB_OK);
3128c941b84Suwe UpdateWindow(_root->_window);
313d1f348c0Such break;
314d1f348c0Such }
315d1f348c0Such argv[argc++] = ptokv(locp);
316d1f348c0Such strncpy(loc, ptr, len);
317d1f348c0Such loc[len] = '\0';
318d1f348c0Such loc += len + 1;
319d1f348c0Such locp += len + 1;
320d1f348c0Such
321d1f348c0Such ptr += len;
322d1f348c0Such while (*ptr == ' ' || *ptr == '\t')
323d1f348c0Such ptr++;
324d1f348c0Such }
325d1f348c0Such
3269173eae7Such return argc;
3279173eae7Such }
3289173eae7Such
3299173eae7Such // kernel bootinfo.
3309173eae7Such void
setup_bootinfo(struct bootinfo & bi)3319173eae7Such HpcMenuInterface::setup_bootinfo(struct bootinfo &bi)
3329173eae7Such {
3339173eae7Such FrameBufferInfo fb(_pref.platid_hi, _pref.platid_lo);
3349173eae7Such TIME_ZONE_INFORMATION tz;
3352ddba961Suwe DWORD tzid = GetTimeZoneInformation(&tz);
3369173eae7Such
3379173eae7Such memset(&bi, 0, sizeof(struct bootinfo));
3389173eae7Such bi.length = sizeof(struct bootinfo);
3399173eae7Such bi.reserved = 0;
3409173eae7Such bi.magic = BOOTINFO_MAGIC;
3419173eae7Such bi.fb_addr = fb.addr();
3429173eae7Such bi.fb_type = fb.type();
3439173eae7Such bi.fb_line_bytes = fb.linebytes();
3449173eae7Such bi.fb_width = fb.width();
3459173eae7Such bi.fb_height = fb.height();
3469173eae7Such bi.platid_cpu = _pref.platid_hi;
3479173eae7Such bi.platid_machine = _pref.platid_lo;
3489173eae7Such bi.timezone = tz.Bias;
3492ddba961Suwe if (tzid == TIME_ZONE_ID_DAYLIGHT)
3502ddba961Suwe bi.timezone += tz.DaylightBias;
3519173eae7Such }
3529173eae7Such
3539173eae7Such // Progress bar
3549173eae7Such void
progress(const char * msg)355b5f1c496Such HpcMenuInterface::progress(const char *msg)
3569173eae7Such {
35732b30275Such
358b5f1c496Such _root->progress(msg);
359f94c4399Suwe }
360f94c4399Suwe
361f94c4399Suwe void
unprogress()362f94c4399Suwe HpcMenuInterface::unprogress()
363f94c4399Suwe {
36432b30275Such
365f94c4399Suwe _root->unprogress();
3669173eae7Such }
367a7876b44Such
368bd926f64Such // Boot kernel.
369a7876b44Such void
boot()370a7876b44Such HpcMenuInterface::boot()
371a7876b44Such {
372a7876b44Such struct support_status *tab = _unsupported;
37324c8a902Suwe uint32_t cpu = _pref.platid_hi;
37424c8a902Suwe uint32_t machine = _pref.platid_lo;
375a7876b44Such
376a7876b44Such if (_pref.safety_message)
377a7876b44Such for (; tab->cpu; tab++) {
378a7876b44Such if (tab->cpu == cpu && tab->machine == machine) {
379a7876b44Such MessageBox(_root->_window,
380a7876b44Such tab->cause ? tab->cause :
381545bd4c3Suwe L"Not supported yet.",
382545bd4c3Suwe TEXT("BOOT FAILED"),
383545bd4c3Suwe MB_ICONERROR | MB_OK);
384a7876b44Such return;
385a7876b44Such }
386a7876b44Such }
387a7876b44Such
388a7876b44Such if (_boot_hook.func)
389bd926f64Such _boot_hook.func(_boot_hook.arg);
390a7876b44Such }
391