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