1 /*	$NetBSD: e32boot.cpp,v 1.3 2013/06/20 15:30:00 kiyohara Exp $	*/
2 /*
3  * Copyright (c) 2012, 2013 KIYOHARA Takashi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <e32base.h>
29 #include <e32cons.h>
30 #include <e32def.h>
31 #include <e32hal.h>
32 #include <e32svr.h>	/* XXXXX */
33 #include <w32std.h>
34 
35 #include "e32boot.h"
36 #include "netbsd.h"
37 #include "../../../include/bootinfo.h"
38 
39 CConsoleBase *console;
40 LOCAL_C NetBSD *LoadNetBSDL(void);
41 LOCAL_C struct btinfo_common *CreateBootInfo(TAny *);
42 LOCAL_C struct btinfo_common *FindBootInfoL(struct btinfo_common *, int);
43 TUint SummaryBootInfoMemory(struct btinfo_common *);
44 LOCAL_C void E32BootL(void);
45 
46 struct memmap {
47 	TUint address;
48 	TUint size;	/* KB */
49 };
50 struct memmap series5_4m[] = {{ 0xc0000000, 512 }, { 0xc0100000, 512 },
51 			      { 0xc0400000, 512 }, { 0xc0500000, 512 },
52 			      { 0xc1000000, 512 }, { 0xc1100000, 512 },
53 			      { 0xc1400000, 512 }, { 0xc1500000, 512 }};
54 struct memmap series5_8m[] = {{ 0xc0000000, 512 }, { 0xc0100000, 512 },
55 			      { 0xc0400000, 512 }, { 0xc0500000, 512 },
56 			      { 0xc1000000, 512 }, { 0xc1100000, 512 },
57 			      { 0xc1400000, 512 }, { 0xc1500000, 512 },
58 			      { 0xd0000000, 512 }, { 0xd0100000, 512 },
59 			      { 0xd0400000, 512 }, { 0xd0500000, 512 },
60 			      { 0xd1000000, 512 }, { 0xd1100000, 512 },
61 			      { 0xd1400000, 512 }, { 0xd1500000, 512 }};
62 struct memmap revo[] = {{ 0xc0000000, 4096 }, { 0xc0800000, 4096 }};
63 struct memmap revopuls[] = {{ 0xc0000000, 4096 }, { 0xc0800000, 4096 },
64 			    { 0xd0000000, 4096 }, { 0xd0800000, 4096 }};
65 struct memmap series5mx_16m[] = {{ 0xc0000000, 8192 }, { 0xc1000000, 8192 }};
66 struct memmap series5mxpro_24m[] = {{ 0xc0000000, 8192 }, { 0xc1000000, 8192 },
67 				    { 0xd0000000, 4096 }, { 0xd0800000, 4096 }};
68 struct memmap series5mxpro_32m[] = {{ 0xc0000000, 8192 }, { 0xc1000000, 8192 },
69 				    { 0xd0000000, 8192 }, { 0xd1000000, 8192 }};
70 struct memmap series7_16m[] = {{ 0xc0000000, 16384 }};
71 struct memmap series7_32m[] = {{ 0xc0000000, 16384 }, { 0xc8000000, 16384 }};
72 
73 struct {
74 	char *model;
75 	TInt width;
76 	TInt height;
77 	TUint memsize;
78 	struct memmap *memmaps;
79 } memmaps[] = {
80 	{ "SERIES5 R1",	640, 240,  4096, series5_4m },
81 	{ "SERIES5 R1",	640, 240,  8192, series5_8m },
82 	{ "SERIES5 R1",	640, 320,  4096, series5_4m },	/* Geofox One */
83 	{ "SERIES5 R1",	640, 320,  8192, series5_8m },	/* Geofox One */
84 //	{ "SERIES5 R1",	640, 320, 16384, one_16m },
85 	{ "SERIES5 R1",	320, 200,  4096, series5_4m },	/* Osaris */
86 //	{ "SERIES5 R1",	320, 200, 16384, osaris_16m },
87 	{ "SERIES5mx",	480, 160,  8192, revo },
88 	{ "SERIES5mx",	480, 160, 16384, revopuls },
89 	{ "SERIES5mx",	640, 240, 16384, series5mx_16m },
90 	{ "SERIES5mx",	640, 240, 24576, series5mxpro_24m },
91 	{ "SERIES5mx",	640, 240, 32768, series5mxpro_32m },
92 	{ "SERIES7",	800, 600, 16384, series7_16m },
93 	{ "SERIES7",	800, 600, 32768, series7_32m },
94 };
95 
96 class E32BootLogicalChannel : public RLogicalChannel {
97 public:
DoCreate(const TDesC * aChan,TInt aUnit,const TDesC * aDriver,const TDesC8 * anInfo)98 	TInt DoCreate(const TDesC *aChan, TInt aUnit, const TDesC *aDriver,
99 							const TDesC8 *anInfo)
100 	{
101 
102 		return RLogicalChannel::DoCreate(E32BootName, TVersion(0, 0, 0),
103 						aChan, aUnit, aDriver, anInfo);
104 	}
105 
DoControl(TInt aFunction,TAny * a1)106 	TInt DoControl(TInt aFunction, TAny *a1)
107 	{
108 
109 		return RLogicalChannel::DoControl(aFunction, a1);
110 	}
111 
DoControl(TInt aFunction,TAny * a1,TAny * a2)112 	TInt DoControl(TInt aFunction, TAny *a1, TAny *a2)
113 	{
114 
115 		return RLogicalChannel::DoControl(aFunction, a1, a2);
116 	}
117 };
118 
119 
120 LOCAL_C void
E32BootL(void)121 E32BootL(void)
122 {
123 	E32BootLogicalChannel *E32BootChannel = new E32BootLogicalChannel;
124 	NetBSD *netbsd = NULL;
125 	TScreenInfoV01 screenInfo;
126 	TPckg<TScreenInfoV01> sI(screenInfo);
127 	TBuf<32> ldd;
128 	TInt err;
129 	TUint membytes;
130 	TAny *buf, *safeAddress;
131 	struct btinfo_common *bootinfo;
132 	struct btinfo_model *model;
133 	struct btinfo_video *video;
134 	struct btinfo_bootargs *bootargs;
135 
136 	console =
137 	    Console::NewL(E32BootName, TSize(KConsFullScreen, KConsFullScreen));
138 
139 	buf = User::AllocL(ALIGN_SAFE_PAGE_SIZE);	/* bootinfo buffer */
140 
141 	/* Put banner */
142 	console->Printf(_L("\n"));
143 	console->Printf(_L(">> %s, Revision %s\n"),
144 	    bootprog_name, bootprog_rev);
145 
146 	UserSvr::ScreenInfo(sI);
147 	if (!screenInfo.iScreenAddressValid)
148 		User::Leave(KErrNotSupported);
149 	safeAddress = screenInfo.iScreenAddress;
150 
151 	bootinfo = CreateBootInfo((TAny *)PAGE_ALIGN(buf));
152 
153 	model = (struct btinfo_model *)FindBootInfoL(bootinfo, BTINFO_MODEL);
154 	console->Printf(_L(">> Model %s\n"), model->model);
155 
156 	membytes = SummaryBootInfoMemory(bootinfo);
157 	console->Printf(_L(">> Memory %d k\n"), membytes / 1024);
158 
159 	video = (struct btinfo_video *)FindBootInfoL(bootinfo, BTINFO_VIDEO);
160 	console->Printf(_L(">> Video %d x %d\n"), video->width, video->height);
161 
162 	console->Printf(_L("\n"));
163 
164 	bootargs =
165 	    (struct btinfo_bootargs *)FindBootInfoL(bootinfo, BTINFO_BOOTARGS);
166 	TRAP(err, netbsd = LoadNetBSDL());
167 	if (err != KErrNone)
168 		User::Leave(err);
169 	else if (netbsd == NULL)
170 		return;
171 	console->Printf(_L("\nLoaded\n"));
172 
173 	int n, m;
174 	n = sizeof(bootargs->bootargs);
175 	m = (*netbsd->GetArgs()).Length();
176 	if (m > 0)
177 		Mem::Copy(bootargs->bootargs, &(*netbsd->GetArgs())[0],
178 		    n < m ? n : m);
179 	bootargs->bootargs[n < m ? n - 1 : m] = '\0';
180 
181 	netbsd->ParseHeader();
182 
183 	/* Load logical device(kernel part of e32boot). */
184 	if (_L(model->model).CompareF(_L("SERIES5 R1")) == 0)
185 		ldd = _L("e32boot-s5.ldd");
186 	else if (_L(model->model).CompareF(_L("SERIES5mx")) == 0)
187 		ldd = _L("e32boot-s5mx.ldd");
188 //	else if (_L(model->model).CompareF(_L("SERIES7")) == 0)
189 //		ldd = _L("e32boot-s7.ldd");	// not yet.
190 	else {
191 		console->Printf(_L("Not Supported machine\n"));
192 		console->Getch();
193 		User::Leave(KErrNotSupported);
194 	}
195 	err = User::LoadLogicalDevice(ldd);
196 	if (err != KErrNone && err != KErrAlreadyExists) {
197 		console->Printf(_L("LoadLogicalDevice failed: %d\n"), err);
198 		console->Getch();
199 		User::Leave(err);
200 	}
201 	/* Create channel to kernel part. */
202 	err = E32BootChannel->DoCreate(NULL, KNullUnit, NULL, NULL);
203 	if (err == KErrNone) {
204 		E32BootChannel->DoControl(KE32BootSetSafeAddress, safeAddress);
205 		E32BootChannel->DoControl(KE32BootBootNetBSD, netbsd, bootinfo);
206 	} else {
207 		console->Printf(_L("DoCreate failed: %d\n"), err);
208 		console->Getch();
209 	}
210 
211 	User::FreeLogicalDevice(ldd);
212 	if (err != KErrNone)
213 		User::Leave(err);
214 }
215 
E32Main(void)216 GLDEF_C TInt E32Main(void)	/* main function called by E32 */
217 {
218 
219 	__UHEAP_MARK;
220 	CTrapCleanup *cleanup = CTrapCleanup::New();
221 
222 	TRAPD(error, E32BootL());
223 	__ASSERT_ALWAYS(!error, User::Panic(E32BootName, error));
224 
225 	delete cleanup;
226 	__UHEAP_MARKEND;
227 	return 0;
228 }
229 
230 LOCAL_C NetBSD *
LoadNetBSDL(void)231 LoadNetBSDL(void)
232 {
233 	NetBSD *netbsd = NULL;
234 	TBuf<KMaxCommandLine> input, *args;
235 	TPtrC Default = _L("C:\\netbsd");
236 	TPtrC Prompt = _L("Boot: ");
237 	TInt pos, err;
238 	TBool retry;
239 
240 	input.Zero();
241 	args = new TBuf<KMaxCommandLine>;
242 	args->Zero();
243 	retry = false;
244 	console->Printf(Prompt);
245 	console->Printf(_L("["));
246 	console->Printf(Default);
247 	console->Printf(_L("]: "));
248 	console->SetPos(Prompt.Length() +
249 			_L("[").Length() +
250 			Default.Length() +
251 			_L("]: ").Length());
252 	pos = 0;
253 	while (1) {
254 		TChar gChar = console->Getch();
255 		switch (gChar) {
256 		case EKeyEscape:
257 			return NULL;
258 
259 		case EKeyEnter:
260 			break;
261 
262 		case EKeyBackspace:
263 			if (pos > 0) {
264 				pos--;
265 				input.Delete(pos, 1);
266 			}
267 			break;
268 
269 		default:
270 			if (gChar.IsPrint()) {
271 				if (input.Length() < KMaxCommandLine) {
272 					TBuf<0x02> b;
273 					b.Append(gChar);
274 					input.Insert(pos++, b);
275 				}
276 			}
277 			break;
278 		}
279 		if (gChar == EKeyEnter) {
280 			input.TrimAll();
281 			if (input[0] == '-')
282 				input.Swap(*args);
283 			for (int i = 0; i < input.Length(); i++)
284 				if (input[i] == ' ') {
285 					args->Copy(input);
286 					input.SetLength(i);
287 					args->Delete(0, i + 1);
288 					break;
289 				}
290 			args->ZeroTerminate();
291 
292 			if (input.Length() > 0) {
293 				TRAP(err, netbsd = NetBSD::New(input, *args));
294 			} else {
295 				TRAP(err, netbsd = NetBSD::New(Default, *args));
296 			}
297 			if (err == 0 && netbsd != NULL)
298 				break;
299 			console->Printf(_L("\nLoad failed: %d\n"), err);
300 
301 			input.Zero();
302 			args->Zero();
303 			console->Printf(Prompt);
304 			pos = 0;
305 			retry = true;
306 		}
307 		TInt base = Prompt.Length();
308 		if (!retry)
309 			base += (_L("[").Length() + Default.Length() +
310 							_L("]: ").Length());
311 		console->SetPos(base + pos);
312 		console->ClearToEndOfLine();
313 		console->SetPos(base);
314 		console->Write(input);
315 		console->SetPos(base + pos);
316 	}
317 
318 	return netbsd;
319 }
320 
321 #define KB	* 1024
322 
323 LOCAL_C struct btinfo_common *
CreateBootInfo(TAny * buf)324 CreateBootInfo(TAny *buf)
325 {
326 	TMachineInfoV1Buf MachInfo;
327 	TMemoryInfoV1Buf MemInfo;
328 	struct btinfo_common *bootinfo, *common;
329 	struct btinfo_model *model;
330 	struct btinfo_memory *memory;
331 	struct btinfo_video *video;
332 	struct btinfo_bootargs *bootargs;
333 	struct memmap *memmap;
334 	TUint memsize;
335 	TUint i;
336 
337 	UserHal::MachineInfo(MachInfo);
338 	UserHal::MemoryInfo(MemInfo);
339 
340 	common = bootinfo = (struct btinfo_common *)buf;
341 
342 	/* Set machine name to bootinfo. */
343 	common->len = sizeof(struct btinfo_model);
344 	common->type = BTINFO_MODEL;
345 	model = (struct btinfo_model *)common;
346 	Mem::Copy(model->model, &MachInfo().iMachineName[0],
347 	    sizeof(model->model));
348 	common = &(model + 1)->common;
349 
350 	/* Set video width/height to bootinfo. */
351 	common->len = sizeof(struct btinfo_video);
352 	common->type = BTINFO_VIDEO;
353 	video = (struct btinfo_video *)common;
354 	video->width = MachInfo().iDisplaySizeInPixels.iWidth;
355 	video->height = MachInfo().iDisplaySizeInPixels.iHeight;
356 	common = &(video + 1)->common;
357 
358 	/* Set memory size to bootinfo. */
359 	memsize = MemInfo().iTotalRamInBytes / 1024;
360 	for (i = 0; i < sizeof(memmaps) / sizeof(memmaps[0]); i++) {
361 		if (_L(memmaps[i].model).CompareF(_L(model->model)) == 0 &&
362 		    memmaps[i].width == video->width &&
363 		    memmaps[i].height == video->height &&
364 		    memmaps[i].memsize == memsize) {
365 			memmap = memmaps[i].memmaps;
366 			while (memsize > 0) {
367 				common->len = sizeof(struct btinfo_memory);
368 				common->type = BTINFO_MEMORY;
369 				memory = (struct btinfo_memory *)common;
370 				memory->address = memmap->address;
371 				memory->size = memmap->size KB;
372 				common = &(memory + 1)->common;
373 				memsize -= memmap->size;
374 				memmap++;
375 			}
376 			break;
377 		}
378 	}
379 	if (i == sizeof(memmaps) / sizeof(memmaps[0])) {
380 		common->len = sizeof(struct btinfo_memory);
381 		common->type = BTINFO_MEMORY;
382 		memory = (struct btinfo_memory *)common;
383 		memory->address = 0xc0000000;		/* default is here */
384 		memory->size = 4096 KB;			/* XXXXX */
385 		common = &(memory + 1)->common;
386 	}
387 
388 	common->len = sizeof(struct btinfo_bootargs);
389 	common->type = BTINFO_BOOTARGS;
390 	bootargs = (struct btinfo_bootargs *)common;
391 	bootargs->bootargs[0] = '\0';
392 	common = &(bootargs + 1)->common;
393 
394 	common->len = 0;
395 	common->type = BTINFO_NONE;
396 
397 	/* Terminate bootinfo. */
398 	return bootinfo;
399 }
400 
401 #undef KB
402 
403 LOCAL_C struct btinfo_common *
FindBootInfoL(struct btinfo_common * bootinfo,int type)404 FindBootInfoL(struct btinfo_common *bootinfo, int type)
405 {
406 	struct btinfo_common *entry;
407 
408 	entry = bootinfo;
409 	while (entry->type != BTINFO_NONE) {
410 		if (entry->type == type)
411 			return entry;
412 		entry = (struct btinfo_common *)((int)entry + entry->len);
413 	}
414 	User::Leave(KErrNotFound);
415 
416 	/* NOTREACHED */
417 
418 	return NULL;
419 }
420 
421 TUint
SummaryBootInfoMemory(struct btinfo_common * bootinfo)422 SummaryBootInfoMemory(struct btinfo_common *bootinfo)
423 {
424 	struct btinfo_common *entry;
425 	struct btinfo_memory *memory;
426 	TUint memsize = 0;
427 
428 	entry = bootinfo;
429 	while (entry->type != BTINFO_NONE) {
430 		if (entry->type == BTINFO_MEMORY) {
431 			memory = (struct btinfo_memory *)entry;
432 			memsize += memory->size;
433 		}
434 		entry = (struct btinfo_common *)((int)entry + entry->len);
435 	}
436 	return memsize;
437 }
438