/* $NetBSD: e32boot.cpp,v 1.3 2013/06/20 15:30:00 kiyohara Exp $ */ /* * Copyright (c) 2012, 2013 KIYOHARA Takashi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include /* XXXXX */ #include #include "e32boot.h" #include "netbsd.h" #include "../../../include/bootinfo.h" CConsoleBase *console; LOCAL_C NetBSD *LoadNetBSDL(void); LOCAL_C struct btinfo_common *CreateBootInfo(TAny *); LOCAL_C struct btinfo_common *FindBootInfoL(struct btinfo_common *, int); TUint SummaryBootInfoMemory(struct btinfo_common *); LOCAL_C void E32BootL(void); struct memmap { TUint address; TUint size; /* KB */ }; struct memmap series5_4m[] = {{ 0xc0000000, 512 }, { 0xc0100000, 512 }, { 0xc0400000, 512 }, { 0xc0500000, 512 }, { 0xc1000000, 512 }, { 0xc1100000, 512 }, { 0xc1400000, 512 }, { 0xc1500000, 512 }}; struct memmap series5_8m[] = {{ 0xc0000000, 512 }, { 0xc0100000, 512 }, { 0xc0400000, 512 }, { 0xc0500000, 512 }, { 0xc1000000, 512 }, { 0xc1100000, 512 }, { 0xc1400000, 512 }, { 0xc1500000, 512 }, { 0xd0000000, 512 }, { 0xd0100000, 512 }, { 0xd0400000, 512 }, { 0xd0500000, 512 }, { 0xd1000000, 512 }, { 0xd1100000, 512 }, { 0xd1400000, 512 }, { 0xd1500000, 512 }}; struct memmap revo[] = {{ 0xc0000000, 4096 }, { 0xc0800000, 4096 }}; struct memmap revopuls[] = {{ 0xc0000000, 4096 }, { 0xc0800000, 4096 }, { 0xd0000000, 4096 }, { 0xd0800000, 4096 }}; struct memmap series5mx_16m[] = {{ 0xc0000000, 8192 }, { 0xc1000000, 8192 }}; struct memmap series5mxpro_24m[] = {{ 0xc0000000, 8192 }, { 0xc1000000, 8192 }, { 0xd0000000, 4096 }, { 0xd0800000, 4096 }}; struct memmap series5mxpro_32m[] = {{ 0xc0000000, 8192 }, { 0xc1000000, 8192 }, { 0xd0000000, 8192 }, { 0xd1000000, 8192 }}; struct memmap series7_16m[] = {{ 0xc0000000, 16384 }}; struct memmap series7_32m[] = {{ 0xc0000000, 16384 }, { 0xc8000000, 16384 }}; struct { char *model; TInt width; TInt height; TUint memsize; struct memmap *memmaps; } memmaps[] = { { "SERIES5 R1", 640, 240, 4096, series5_4m }, { "SERIES5 R1", 640, 240, 8192, series5_8m }, { "SERIES5 R1", 640, 320, 4096, series5_4m }, /* Geofox One */ { "SERIES5 R1", 640, 320, 8192, series5_8m }, /* Geofox One */ // { "SERIES5 R1", 640, 320, 16384, one_16m }, { "SERIES5 R1", 320, 200, 4096, series5_4m }, /* Osaris */ // { "SERIES5 R1", 320, 200, 16384, osaris_16m }, { "SERIES5mx", 480, 160, 8192, revo }, { "SERIES5mx", 480, 160, 16384, revopuls }, { "SERIES5mx", 640, 240, 16384, series5mx_16m }, { "SERIES5mx", 640, 240, 24576, series5mxpro_24m }, { "SERIES5mx", 640, 240, 32768, series5mxpro_32m }, { "SERIES7", 800, 600, 16384, series7_16m }, { "SERIES7", 800, 600, 32768, series7_32m }, }; class E32BootLogicalChannel : public RLogicalChannel { public: TInt DoCreate(const TDesC *aChan, TInt aUnit, const TDesC *aDriver, const TDesC8 *anInfo) { return RLogicalChannel::DoCreate(E32BootName, TVersion(0, 0, 0), aChan, aUnit, aDriver, anInfo); } TInt DoControl(TInt aFunction, TAny *a1) { return RLogicalChannel::DoControl(aFunction, a1); } TInt DoControl(TInt aFunction, TAny *a1, TAny *a2) { return RLogicalChannel::DoControl(aFunction, a1, a2); } }; LOCAL_C void E32BootL(void) { E32BootLogicalChannel *E32BootChannel = new E32BootLogicalChannel; NetBSD *netbsd = NULL; TScreenInfoV01 screenInfo; TPckg sI(screenInfo); TBuf<32> ldd; TInt err; TUint membytes; TAny *buf, *safeAddress; struct btinfo_common *bootinfo; struct btinfo_model *model; struct btinfo_video *video; struct btinfo_bootargs *bootargs; console = Console::NewL(E32BootName, TSize(KConsFullScreen, KConsFullScreen)); buf = User::AllocL(ALIGN_SAFE_PAGE_SIZE); /* bootinfo buffer */ /* Put banner */ console->Printf(_L("\n")); console->Printf(_L(">> %s, Revision %s\n"), bootprog_name, bootprog_rev); UserSvr::ScreenInfo(sI); if (!screenInfo.iScreenAddressValid) User::Leave(KErrNotSupported); safeAddress = screenInfo.iScreenAddress; bootinfo = CreateBootInfo((TAny *)PAGE_ALIGN(buf)); model = (struct btinfo_model *)FindBootInfoL(bootinfo, BTINFO_MODEL); console->Printf(_L(">> Model %s\n"), model->model); membytes = SummaryBootInfoMemory(bootinfo); console->Printf(_L(">> Memory %d k\n"), membytes / 1024); video = (struct btinfo_video *)FindBootInfoL(bootinfo, BTINFO_VIDEO); console->Printf(_L(">> Video %d x %d\n"), video->width, video->height); console->Printf(_L("\n")); bootargs = (struct btinfo_bootargs *)FindBootInfoL(bootinfo, BTINFO_BOOTARGS); TRAP(err, netbsd = LoadNetBSDL()); if (err != KErrNone) User::Leave(err); else if (netbsd == NULL) return; console->Printf(_L("\nLoaded\n")); int n, m; n = sizeof(bootargs->bootargs); m = (*netbsd->GetArgs()).Length(); if (m > 0) Mem::Copy(bootargs->bootargs, &(*netbsd->GetArgs())[0], n < m ? n : m); bootargs->bootargs[n < m ? n - 1 : m] = '\0'; netbsd->ParseHeader(); /* Load logical device(kernel part of e32boot). */ if (_L(model->model).CompareF(_L("SERIES5 R1")) == 0) ldd = _L("e32boot-s5.ldd"); else if (_L(model->model).CompareF(_L("SERIES5mx")) == 0) ldd = _L("e32boot-s5mx.ldd"); // else if (_L(model->model).CompareF(_L("SERIES7")) == 0) // ldd = _L("e32boot-s7.ldd"); // not yet. else { console->Printf(_L("Not Supported machine\n")); console->Getch(); User::Leave(KErrNotSupported); } err = User::LoadLogicalDevice(ldd); if (err != KErrNone && err != KErrAlreadyExists) { console->Printf(_L("LoadLogicalDevice failed: %d\n"), err); console->Getch(); User::Leave(err); } /* Create channel to kernel part. */ err = E32BootChannel->DoCreate(NULL, KNullUnit, NULL, NULL); if (err == KErrNone) { E32BootChannel->DoControl(KE32BootSetSafeAddress, safeAddress); E32BootChannel->DoControl(KE32BootBootNetBSD, netbsd, bootinfo); } else { console->Printf(_L("DoCreate failed: %d\n"), err); console->Getch(); } User::FreeLogicalDevice(ldd); if (err != KErrNone) User::Leave(err); } GLDEF_C TInt E32Main(void) /* main function called by E32 */ { __UHEAP_MARK; CTrapCleanup *cleanup = CTrapCleanup::New(); TRAPD(error, E32BootL()); __ASSERT_ALWAYS(!error, User::Panic(E32BootName, error)); delete cleanup; __UHEAP_MARKEND; return 0; } LOCAL_C NetBSD * LoadNetBSDL(void) { NetBSD *netbsd = NULL; TBuf input, *args; TPtrC Default = _L("C:\\netbsd"); TPtrC Prompt = _L("Boot: "); TInt pos, err; TBool retry; input.Zero(); args = new TBuf; args->Zero(); retry = false; console->Printf(Prompt); console->Printf(_L("[")); console->Printf(Default); console->Printf(_L("]: ")); console->SetPos(Prompt.Length() + _L("[").Length() + Default.Length() + _L("]: ").Length()); pos = 0; while (1) { TChar gChar = console->Getch(); switch (gChar) { case EKeyEscape: return NULL; case EKeyEnter: break; case EKeyBackspace: if (pos > 0) { pos--; input.Delete(pos, 1); } break; default: if (gChar.IsPrint()) { if (input.Length() < KMaxCommandLine) { TBuf<0x02> b; b.Append(gChar); input.Insert(pos++, b); } } break; } if (gChar == EKeyEnter) { input.TrimAll(); if (input[0] == '-') input.Swap(*args); for (int i = 0; i < input.Length(); i++) if (input[i] == ' ') { args->Copy(input); input.SetLength(i); args->Delete(0, i + 1); break; } args->ZeroTerminate(); if (input.Length() > 0) { TRAP(err, netbsd = NetBSD::New(input, *args)); } else { TRAP(err, netbsd = NetBSD::New(Default, *args)); } if (err == 0 && netbsd != NULL) break; console->Printf(_L("\nLoad failed: %d\n"), err); input.Zero(); args->Zero(); console->Printf(Prompt); pos = 0; retry = true; } TInt base = Prompt.Length(); if (!retry) base += (_L("[").Length() + Default.Length() + _L("]: ").Length()); console->SetPos(base + pos); console->ClearToEndOfLine(); console->SetPos(base); console->Write(input); console->SetPos(base + pos); } return netbsd; } #define KB * 1024 LOCAL_C struct btinfo_common * CreateBootInfo(TAny *buf) { TMachineInfoV1Buf MachInfo; TMemoryInfoV1Buf MemInfo; struct btinfo_common *bootinfo, *common; struct btinfo_model *model; struct btinfo_memory *memory; struct btinfo_video *video; struct btinfo_bootargs *bootargs; struct memmap *memmap; TUint memsize; TUint i; UserHal::MachineInfo(MachInfo); UserHal::MemoryInfo(MemInfo); common = bootinfo = (struct btinfo_common *)buf; /* Set machine name to bootinfo. */ common->len = sizeof(struct btinfo_model); common->type = BTINFO_MODEL; model = (struct btinfo_model *)common; Mem::Copy(model->model, &MachInfo().iMachineName[0], sizeof(model->model)); common = &(model + 1)->common; /* Set video width/height to bootinfo. */ common->len = sizeof(struct btinfo_video); common->type = BTINFO_VIDEO; video = (struct btinfo_video *)common; video->width = MachInfo().iDisplaySizeInPixels.iWidth; video->height = MachInfo().iDisplaySizeInPixels.iHeight; common = &(video + 1)->common; /* Set memory size to bootinfo. */ memsize = MemInfo().iTotalRamInBytes / 1024; for (i = 0; i < sizeof(memmaps) / sizeof(memmaps[0]); i++) { if (_L(memmaps[i].model).CompareF(_L(model->model)) == 0 && memmaps[i].width == video->width && memmaps[i].height == video->height && memmaps[i].memsize == memsize) { memmap = memmaps[i].memmaps; while (memsize > 0) { common->len = sizeof(struct btinfo_memory); common->type = BTINFO_MEMORY; memory = (struct btinfo_memory *)common; memory->address = memmap->address; memory->size = memmap->size KB; common = &(memory + 1)->common; memsize -= memmap->size; memmap++; } break; } } if (i == sizeof(memmaps) / sizeof(memmaps[0])) { common->len = sizeof(struct btinfo_memory); common->type = BTINFO_MEMORY; memory = (struct btinfo_memory *)common; memory->address = 0xc0000000; /* default is here */ memory->size = 4096 KB; /* XXXXX */ common = &(memory + 1)->common; } common->len = sizeof(struct btinfo_bootargs); common->type = BTINFO_BOOTARGS; bootargs = (struct btinfo_bootargs *)common; bootargs->bootargs[0] = '\0'; common = &(bootargs + 1)->common; common->len = 0; common->type = BTINFO_NONE; /* Terminate bootinfo. */ return bootinfo; } #undef KB LOCAL_C struct btinfo_common * FindBootInfoL(struct btinfo_common *bootinfo, int type) { struct btinfo_common *entry; entry = bootinfo; while (entry->type != BTINFO_NONE) { if (entry->type == type) return entry; entry = (struct btinfo_common *)((int)entry + entry->len); } User::Leave(KErrNotFound); /* NOTREACHED */ return NULL; } TUint SummaryBootInfoMemory(struct btinfo_common *bootinfo) { struct btinfo_common *entry; struct btinfo_memory *memory; TUint memsize = 0; entry = bootinfo; while (entry->type != BTINFO_NONE) { if (entry->type == BTINFO_MEMORY) { memory = (struct btinfo_memory *)entry; memsize += memory->size; } entry = (struct btinfo_common *)((int)entry + entry->len); } return memsize; }