1/*	$NetBSD: hpcboot.cpp,v 1.19 2006/03/05 04:05:39 uwe Exp $	*/
2
3/*-
4 * Copyright (c) 2001, 2002, 2004 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 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <hpcmenu.h>
33#include <hpcboot.h>
34
35#include <menu/window.h>
36#include <menu/rootwindow.h>
37
38#include <console.h>
39#include <arch.h>
40#include <memory.h>
41#include <file.h>
42#include <load.h>
43
44#include <boot.h>
45
46#include "../binary/build_number.h"
47
48#if _WIN32_WCE <= 200
49OSVERSIONINFO WinCEVersion;
50#else
51OSVERSIONINFOW WinCEVersion;
52#endif
53
54int WINAPI
55WinMain(HINSTANCE instance, HINSTANCE prev_instance,
56    LPTSTR cmd_line, int window_show)
57{
58	HpcMenuInterface::Instance();	// Menu System
59	HpcBootApp *app = 0;		// Application body.
60	int ret = 0;
61
62	InitCommonControls();
63
64	app = new HpcBootApp(instance);
65	app->_cons = Console::Instance();
66	app->_root = new RootWindow(*app);
67
68	if (!app->registerClass(reinterpret_cast <WNDPROC>(Window::_wnd_proc)))
69		goto failed;
70
71	if (!app->_root->create(0))
72		goto failed;
73
74	Boot::Instance();	// Boot loader
75
76	ret = app->run();	// Main loop.
77	// NOTREACHED
78
79 failed:
80
81	Boot::Destroy();
82	if (app->_root)
83		delete app->_root;
84	delete app;
85	Console::Destroy();
86	HpcMenuInterface::Destroy();
87
88	return ret;
89}
90
91//
92// boot sequence.
93//
94void
95hpcboot(void *arg)
96{
97	size_t sz = 0;
98	paddr_t p = 0;
99	TCHAR *error_message = 0;
100
101	HpcMenuInterface &menu = HPC_MENU;
102	Boot &f = Boot::Instance();
103
104	// Open serial port for kernel KGDB.
105	SerialConsole::OpenCOM1();
106
107	menu.progress("0");
108	if (!f.setup()) {
109		error_message = TEXT("Architecture not supported.\n");
110		goto failed_exit;
111	}
112
113	menu.progress("1");
114	if (!f.create()) {
115		error_message = TEXT("Architecture ops. not found.\n");
116		goto failed_exit;
117	}
118
119	// Now we can write console which user specified.
120	{
121		DPRINTF_SETUP();
122		DPRINTF((TEXT("hpcboot build number: %d\n"),
123		    HPCBOOT_BUILD_NUMBER));
124		DPRINTF((TEXT("%s (cpu=0x%08x machine=0x%08x)\n"),
125		    HPC_MENU.platform_get(HPC_MENU.platform_default()),
126		    HPC_PREFERENCE.platid_hi, HPC_PREFERENCE.platid_lo));
127	}
128
129	menu.progress("2");
130	if (!f._arch->init()) {
131		error_message = TEXT("Architecture initialize failed.\n");
132		goto failed_exit;
133	}
134
135	f._arch->systemInfo();
136
137	menu.progress("3");
138	// kernel / file system image directory.
139	if (!f._file->setRoot(f.args.fileRoot)) {
140		error_message = TEXT("Can't set root directory.\n");
141		goto failed_exit;
142	}
143
144	// determine the size of file system image.
145	if (f.args.loadmfs)
146	{
147		if (!f._file->open(f.args.mfsName)) {
148			error_message =
149			    TEXT("Can't open file system image.\n");
150			goto failed_exit;
151		}
152		sz = f._file->realsize();
153		sz = f._mem->roundPage(sz);
154		f._file->close();
155	}
156
157	menu.progress("4");
158	if (!f._file->open(f.args.fileName)) {
159		error_message = TEXT("Can't open kernel image.\n");
160		goto failed_exit;
161	}
162
163	menu.progress("5");
164	// put kernel to loader.
165	if (!f.attachLoader()) {
166		error_message = TEXT("Can't attach loader.\n");
167		goto file_close_exit;
168	}
169
170	if (!f._loader->setFile(f._file)) {
171		error_message = TEXT("Can't initialize loader.\n");
172		goto file_close_exit;
173	}
174
175	menu.progress("6");
176	sz += f._mem->roundPage(f._loader->memorySize());
177
178	// allocate required memory.
179	if (!f._arch->allocateMemory(sz)) {
180		error_message = TEXT("Can't allocate memory.\n");
181		goto file_close_exit;
182	}
183
184	menu.progress("7");
185	// load kernel to memory.
186	if (!f._arch->setupLoader()) {
187		error_message = TEXT("Can't set up loader.\n");
188		goto file_close_exit;
189	}
190
191	menu.progress("8");
192	if (!f._loader->load()) {
193		error_message = TEXT("Can't load kernel image to memory.\n");
194		goto file_close_exit;
195	}
196	menu.progress("9");
197	f._file->close();
198
199	// load file system image to memory
200	if (f.args.loadmfs) {
201		if (!f._file->open(f.args.mfsName)) {
202			error_message =
203			    TEXT("Can't open file system image.\n");
204			goto failed_exit;
205		}
206		if (!f._loader->loadExtData()) {
207			error_message =
208			    TEXT("Can't load file system image to memory.\n");
209			goto file_close_exit;
210		}
211		f._file->close();
212	}
213	f._loader->loadEnd();
214
215	// setup arguments for kernel.
216	p = f._arch->setupBootInfo(*f._loader);
217
218	menu.progress("10");
219
220	f._loader->tagDump(3); // dump page chain.(print first 3 links)
221
222	// jump to kernel entry.
223	if (HPC_PREFERENCE.pause_before_boot) {
224		if (MessageBox(menu._root->_window, TEXT("Push YES to boot."),
225		    TEXT("Last chance..."),
226		    MB_ICONWARNING | MB_YESNO) != IDYES)
227		{
228			error_message = TEXT("Canceled by user.\n");
229			goto failed_exit;
230		}
231		// redraw areas damaged by the dialog
232		UpdateWindow(menu._root->_window);
233	}
234
235	f._arch->jump(p, f._loader->tagStart());
236	// NOTREACHED
237	error_message = TEXT("Can't jump to the kernel.\n");
238
239 file_close_exit:
240	f._file->close();
241
242 failed_exit:
243	if (error_message == 0)
244		error_message = TEXT("Unknown error?\n");
245	MessageBox(menu._root->_window, error_message,
246	    TEXT("BOOT FAILED"), MB_ICONERROR | MB_OK);
247
248	menu.unprogress();	// rewind progress bar
249}
250
251//
252// HPCBOOT main loop
253//
254int
255HpcBootApp::run(void)
256{
257	MSG msg;
258
259	while (GetMessage(&msg, 0, 0, 0)) {
260		// cancel auto-boot.
261		if (HPC_PREFERENCE.auto_boot > 0 && _root &&
262		    (msg.message == WM_KEYDOWN ||
263			msg.message == WM_LBUTTONDOWN)) {
264			_root->disableTimer();
265		}
266		if (!_root->isDialogMessage(msg)) {
267			TranslateMessage(&msg);
268			DispatchMessage(&msg);
269		}
270	}
271	return msg.wParam;
272}
273
274BOOL
275HpcBootApp::registerClass(WNDPROC proc)
276{
277	TCHAR *wc_name;
278	WNDCLASS wc;
279
280	memset(&wc, 0, sizeof(WNDCLASS));
281	wc_name		= reinterpret_cast <TCHAR *>
282	    (LoadString(_instance, IDS_HPCMENU, 0, 0));
283	wc.lpfnWndProc	= proc;
284	wc.hInstance	= _instance;
285	wc.hIcon	= LoadIcon(_instance, MAKEINTRESOURCE(IDI_ICON));
286	wc.cbWndExtra	= 4;		// pointer of `this`
287	wc.hbrBackground= static_cast <HBRUSH>(GetStockObject(LTGRAY_BRUSH));
288	wc.lpszClassName= wc_name;
289
290	return RegisterClass(&wc);
291}
292
293
294//
295// Debug support.
296//
297void
298_bitdisp(uint32_t a, int s, int e, int m, int c)
299{
300	uint32_t j, j1;
301	int i, n;
302
303	DPRINTF_SETUP();
304
305	n = 31;	// 32bit only.
306	j1 = 1 << n;
307	e = e ? e : n;
308	for (j = j1, i = n; j > 0; j >>=1, i--) {
309		if (i > e || i < s) {
310			DPRINTF((TEXT("%c"), a & j ? '+' : '-'));
311		} else {
312			DPRINTF((TEXT("%c"), a & j ? '|' : '.'));
313		}
314	}
315	if (m) {
316		DPRINTF((TEXT("[%s]"),(char*)m));
317	}
318
319	DPRINTF((TEXT(" [0x%08x]"), a));
320
321	if (c) {
322		for (j = j1, i = n; j > 0; j >>=1, i--) {
323			if (!(i > e || i < s) &&(a & j)) {
324				DPRINTF((TEXT(" %d"), i));
325			}
326		}
327	}
328
329	DPRINTF((TEXT(" %d\n"), a));
330}
331
332void
333_dbg_bit_print(uint32_t reg, uint32_t mask, const char *name)
334{
335	static const char onoff[3] = "_x";
336
337	DPRINTF_SETUP();
338
339	DPRINTF((TEXT("%S[%c] "), name, onoff[reg & mask ? 1 : 0]));
340}
341