moved prestart sources to their own directory and set up the section names

they use with a custom linker script
This commit is contained in:
Eric J. Bowersox
2013-05-02 23:16:55 -06:00
parent eda9737083
commit 4cf088683f
9 changed files with 279 additions and 67 deletions

43
kernel/prestart/Makefile Normal file
View File

@@ -0,0 +1,43 @@
#
# This file is part of the COMROGUE Operating System for Raspberry Pi
#
# Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
# All rights reserved.
#
# This program is free for commercial and non-commercial use as long as the following conditions are
# adhered to.
#
# Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
# in the code are not to be removed.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted
# provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this list of conditions and
# the following disclaimer.
# * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
#
# "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
MAKEFLAGS += -rR
CRBASEDIR := $(abspath ../..)
include $(CRBASEDIR)/armcompile.mk
PRESTART_OBJS = prestart.o early_trace.o collect_startup.o early_mm.o
all: kernel-prestart.o
kernel-prestart.o: $(PRESTART_OBJS) kernel-prestart.lds
$(LD) -r -T kernel-prestart.lds $(PRESTART_OBJS) -o kernel-prestart.o
clean:
-rm *.o *.s *.lds

View File

@@ -0,0 +1,247 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#define __COMROGUE_PRESTART__
#include <comrogue/types.h>
#include <comrogue/internals/mmu.h>
#include <comrogue/internals/seg.h>
#include <comrogue/internals/startup.h>
/* The startup information buffer. */
static STARTUP_INFO startup_info = {
.cb = sizeof(STARTUP_INFO),
.paTTB = 0,
.kaTTB = 0,
.cpgTTBGap = 0,
.paTTBAux = 0,
.kaTTBAux = 0,
.paMPDB = 0,
.kaMPDB = 0,
.cpgMPDB = 0,
.paFirstPageTable = 0,
.cpgPageTables = 0,
.ctblFreeOnLastPage = 0,
.paFirstFree = 0,
.vmaFirstFree = 0
};
/*
* Find a variable by name on the command line.
*
* Parameters:
* - pszCmdLine = Command-line pointer.
* - pszVariableName = Name of variable to search for.
*
* Returns:
* NULL if the variable was not found, otherwise a pointer to the first character in the command line
* following the variable name and associated = sign (first character of the value).
*/
static PCSTR find_variable(PCSTR pszCmdLine, PCSTR pszVariableName)
{
register PCSTR p = pszCmdLine;
register PCSTR p1, q;
while (*p)
{
for (; *p && (*p != *pszVariableName); p++) ;
if (*p)
{
for (p1 = p, q = pszVariableName; *p1 && *q && (*p1 == *q); p1++, q++) ;
if (!(*q) && *p1 == '=')
return p1 + 1;
p++;
}
}
return NULL;
}
/*
* Returns whether a character is a valid digit.
*
* Parameters:
* - ch = The character to be tested.
* - base = The base of the number being converted.
*
* Returns:
* TRUE if the character is a valid digit, FALSE otherwise.
*/
static BOOL is_valid_digit(CHAR ch, UINT32 base)
{
register UINT32 nbase;
if (base > 10)
{
if ((ch >= 'a') && (ch < ('a' + base - 10)))
return TRUE;
if ((ch >= 'A') && (ch < ('A' + base - 10)))
return TRUE;
}
nbase = (base > 10) ? 10 : base;
if ((ch >= '0') && (ch < ('0' + nbase)))
return TRUE;
return FALSE;
}
/*
* Decodes a number in a command-line parameter. Decoding stops at the first character that is not a valid digit.
*
* Parameters:
* - pVal = Pointer to the value in the command line.
* - base = Base of the number to convert. If this is 16, the decoder will skip over a "0x" or "0X" prefix
* of the value, if one exists.
*
* Returns:
* The converted numeric value.
*/
static UINT32 decode_number(PCSTR pVal, UINT32 base)
{
register UINT32 accum = 0;
register UINT32 digit;
if ((base == 16) && (*pVal == '0') && ((*(pVal + 1) == 'x') || (*(pVal + 1) == 'X')))
pVal += 2;
while (is_valid_digit(*pVal, base))
{
if (*pVal >= 'a')
digit = (*pVal - 'a') + 10;
else if (*pVal >= 'A')
digit = (*pVal - 'A') + 10;
else
digit = (*pVal - '0');
accum = accum * base + digit;
pVal++;
}
return accum;
}
/*
* Parses the command line passed in via the ATAGS and extracts certain values to the startup info
* data structure.
*
* Parameters:
* - pszCmdLine = Pointer to the command line.
*
* Returns:
* Nothing.
*
* Side effects:
* Modifies the "startup_info" structure.
*/
static void parse_cmdline(PCSTR pszCmdLine)
{
static DECLARE_STRING8_CONST(szFBWidth, "bcm2708_fb.fbwidth");
static DECLARE_STRING8_CONST(szFBHeight, "bcm2708_fb.fbheight");
static DECLARE_STRING8_CONST(szRevision, "bcm2708.boardrev");
static DECLARE_STRING8_CONST(szSerial, "bcm2708.serial");
static DECLARE_STRING8_CONST(szMACAddr, "smsc95xx.macaddr");
static DECLARE_STRING8_CONST(szEMMCFreq, "sdhci-bcm2708.emmc_clock_freq");
static DECLARE_STRING8_CONST(szVCMemBase, "vc_mem.mem_base");
static DECLARE_STRING8_CONST(szVCMemSize, "vc_mem.mem_size");
register PCSTR p;
register int i;
p = find_variable(pszCmdLine, szFBWidth);
startup_info.cxFBWidth = (UINT16)(p ? decode_number(p, 10) : 0);
p = find_variable(pszCmdLine, szFBHeight);
startup_info.cyFBHeight = (UINT16)(p ? decode_number(p, 10) : 0);
p = find_variable(pszCmdLine, szRevision);
startup_info.uiRevision = (p ? decode_number(p, 16) : 0);
p = find_variable(pszCmdLine, szSerial);
startup_info.uiSerialNumber = (p ? decode_number(p, 16) : 0);
p = find_variable(pszCmdLine, szMACAddr);
if (p)
{
for (i=0; i<6; i++)
{
startup_info.abMACAddress[i] = (BYTE)decode_number(p, 16);
p += 3;
}
}
else
{
for (i=0; i<6; i++)
startup_info.abMACAddress[i] = 0;
}
p = find_variable(pszCmdLine, szEMMCFreq);
startup_info.uiEMMCClockFreq = (p ? decode_number(p, 10) : 0);
p = find_variable(pszCmdLine, szVCMemBase);
startup_info.paVCMem = (PHYSADDR)(p ? decode_number(p, 16) : 0);
p = find_variable(pszCmdLine, szVCMemSize);
startup_info.cbVCMem = (p ? decode_number(p, 16) : 0);
startup_info.cpgSystemTotal = startup_info.cbVCMem >> SYS_PAGE_BITS;
}
/*
* Collects startup information in an init-data buffer and returns a pointer to that buffer.
*
* Parameters:
* - always0 = Always 0.
* - uiMachineType = Machine type constant.
* - pAtags = Pointer to ATAGS data set up before kernel was started.
*
* Returns:
* A pointer to the assembled STARTUP_INFO data structure.
*
* Side effects:
* Modifies the "startup_info" structure, which it returns a pointer to.
*/
PSTARTUP_INFO KiCollectStartupInfo(UINT32 always0, UINT32 uiMachineType, PATAG_HEADER pAtags)
{
/* Fill in the information we can calculate right away. */
startup_info.uiMachineType = uiMachineType;
/* Scan the ATAG headers to determine what other info to include. */
while (pAtags->uiTag != ATAGTYPE_NONE)
{
switch (pAtags->uiTag)
{
case ATAGTYPE_CORE:
/* nothing really useful in this block */
break;
case ATAGTYPE_MEM:
/* fill in total number of available system memory pages */
startup_info.cpgSystemAvail = ((PATAG_MEM)pAtags)->uiSize >> SYS_PAGE_BITS;
break;
case ATAGTYPE_CMDLINE:
parse_cmdline(((PATAG_CMDLINE)pAtags)->szCommandLine);
break;
default:
/* no other ATAG types are seen on Raspberry Pi */
break;
}
pAtags = kiNextATAG(pAtags);
}
return &startup_info;
}

472
kernel/prestart/early_mm.c Normal file
View File

@@ -0,0 +1,472 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#define __COMROGUE_PRESTART__
#include <comrogue/types.h>
#include <comrogue/internals/layout.h>
#include <comrogue/internals/mmu.h>
#include <comrogue/internals/startup.h>
#include <comrogue/internals/trace.h>
#ifdef THIS_FILE
#undef THIS_FILE
DECLARE_THIS_FILE
#endif
/*-----------------------------------------------------------------------------
* Early memory-management code that handles creating the mappings for the TTB
*-----------------------------------------------------------------------------
*/
/* Data stored in here temporarily and reflected back to startup info when we're done. */
static PTTB g_pTTB; /* pointer to TTB */
static PTTBAUX g_pTTBAux; /* pointer to TTB auxiliary data */
static UINT32 g_cpgForPageTables; /* number of pages being used for page tables */
static UINT32 g_ctblFreeonLastPage; /* number of page tables free on last page */
static PPAGETAB g_ptblNext; /* pointer to next free page table */
/*
* Morphs the "flags" bits used for a page table entry in the TTB and for a page entry in the page table
* into the "flags" bits used for a section entry in the TTB.
*
* Parameters:
* - uiTableFlags = Flag bits that would be used for a page table entry in the TTB.
* - uiPageFlags = Flag bits that would be used for a page entry in the page table.
*
* Returns:
* The flag bits that would be used for a section entry in the TTB. If a bit or option is set
* in either uiTableFlags or uiPageFlags, it will be set in the appropriate place in the result.
*/
static UINT32 make_section_flags(UINT32 uiTableFlags, UINT32 uiPageFlags)
{
register UINT32 rc = TTBSEC_ALWAYS;
rc |= ((uiTableFlags & TTBPGTBL_PXN) >> 2);
rc |= ((uiTableFlags & TTBPGTBL_NS) << 16);
rc |= (uiTableFlags & TTBPGTBL_DOM_MASK);
rc |= (uiTableFlags & TTBPGTBL_P);
rc |= ((uiPageFlags & PGTBLSM_XN) << 4);
rc |= (uiPageFlags & PGTBLSM_B);
rc |= (uiPageFlags & PGTBLSM_C);
rc |= ((uiPageFlags & PGTBLSM_AP) << 6);
rc |= ((uiPageFlags & PGTBLSM_TEX) << 6);
rc |= ((uiPageFlags & PGTBLSM_APX) << 6);
rc |= ((uiPageFlags & PGTBLSM_S) << 6);
rc |= ((uiPageFlags & PGTBLSM_NG) << 6);
return rc;
}
/*
* Morphs the "auxiliary flags" bits used for a page table entry into "auxiliary flags" used for a TTB entry.
*
* Parameters:
* - uiPageAuxFlags = Page auxiliary flag bits that would be used for a page table entry.
*
* Returns:
* TTB auxiliary flag bits that would be used for a TTB entry.
*/
static UINT32 make_section_aux_flags(UINT32 uiPageAuxFlags)
{
register UINT32 rc = uiPageAuxFlags & (PGAUX_SACRED|PGAUX_UNWRITEABLE);
/* TODO if we define any other flags */
return rc;
}
/*
* Allocates a new page table, initializes it, and initializes the pointed-to TTB entry with a
* pointer to it.
*
* Parameters:
* - pTTBEntry = Pointer to the TTB entry to be filled; this entry is modified.
* - pAuxEntry = Pointer to the TTB aux entry to be filled; this entry is modified.
* - uiTableFlags = Flags to be used for the TTB entry.
*
* Returns:
* A pointer to the new page table.
*
* Side effects:
* Modifies the global variables g_cpgForPageTables, g_ctblFreeonLastPage, and g_ptblNext.
*/
static PPAGETAB alloc_page_table(PTTB pTTBEntry, PTTBAUX pAuxEntry, UINT32 uiTableFlags)
{
register PPAGETAB pTab; /* pointer to new page table */
register UINT32 i; /* loop counter */
if (g_ctblFreeonLastPage == 0)
{
g_cpgForPageTables++;
g_ctblFreeonLastPage = 2;
}
g_ctblFreeonLastPage--;
pTab = g_ptblNext++;
for (i=0; i<SYS_PGTBL_ENTRIES; i++)
{
pTab->pgtbl[i].data = 0; /* blank out the new page table */
pTab->pgaux[i].data = 0;
}
pTTBEntry->data = ((UINT32)pTab) | uiTableFlags; /* poke new entry */
pAuxEntry->data = TTBAUXFLAGS_PAGETABLE;
return pTab;
}
/*
* Allocates page mapping entries within a single current entry in the TTB.
*
* Parameters:
* - paBase = The page-aligned base physical address to map.
* - pTTBEntry = Pointer to the TTB entry to be used.
* - pAuxEntry = Pointer to the TTB auxiliary entry to be used.
* - ndxPage = The "first" index within the current page to use.
* - cpg = The maximum number of pages we want to map. This function will only map as many pages as will
* fit in the current TTB entry, as indicated by ndxPage.
* - uiTableFlags = Flags to be used or verified for the TTB entry.
* - uiPageFlags = Flags to be used for new page table entries.
* - uiAuxFlags = Flags to be used for new page table auxiliary entries.
*
* Returns:
* The number of pages that were actually mapped by this function call, or -1 if there was an error in the mapping.
*
* Side effects:
* May modify the TTB entry we point to, if it was not previously allocated. May modify the current page
* table that the TTB entry points to, where applicable. If we need to allocate a new page table, may modify the
* global variables g_cpgForPageTables, g_ctblFreeonLastPage, and g_ptblNext.
*/
static INT32 alloc_pages(PHYSADDR paBase, PTTB pTTBEntry, PTTBAUX pAuxEntry, INT32 ndxPage,
INT32 cpg, UINT32 uiTableFlags, UINT32 uiPageFlags, UINT32 uiAuxFlags)
{
INT32 cpgCurrent; /* number of pages we're mapping */
PPAGETAB pTab; /* pointer to current or new page table */
register INT32 i; /* loop counter */
switch (pTTBEntry->data & TTBQUERY_MASK)
{
case TTBQUERY_FAULT: /* not allocated, allocate a new page table for the slot */
pTab = alloc_page_table(pTTBEntry, pAuxEntry, uiTableFlags);
break;
case TTBQUERY_PGTBL: /* existing page table */
if ((pTTBEntry->data & TTBPGTBL_ALLFLAGS) != uiTableFlags)
return -1; /* table flags not compatible */
pTab = (PPAGETAB)(pTTBEntry->data & TTBPGTBL_BASE);
break;
case TTBQUERY_SEC:
case TTBQUERY_PXNSEC: /* existing section */
if ((pTTBEntry->data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags))
return -1;
if (pAuxEntry->data != make_section_aux_flags(uiAuxFlags))
return -1;
if ((pTTBEntry->data & TTBSEC_BASE) != (paBase & TTBSEC_BASE))
return -1;
pTab = NULL;
break;
}
/* Figure out how many entries we're going to map. */
cpgCurrent = SYS_PGTBL_ENTRIES - ndxPage; /* total free slots on page */
if (cpg < cpgCurrent)
cpgCurrent = cpg; /* only map up to max requested */
if (pTab)
{ /* fill in entries in the page table */
for (i=0; i<cpgCurrent; i++)
{
if ((pTab->pgtbl[ndxPage + i].data & PGQUERY_MASK) != PGQUERY_FAULT)
return -1; /* stepping on existing mapping */
pTab->pgtbl[ndxPage + i].data = paBase | uiPageFlags;
pTab->pgaux[ndxPage + i].data = uiAuxFlags;
paBase += SYS_PAGE_SIZE;
}
}
return cpgCurrent;
}
/*
* Maps a certain number of memory pages beginning at a specified physical address into virtual memory
* beginning at a specified virtual address.
*
* Parameters:
* - paBase = The page-aligned base physical address to map.
* - vmaBase = The page-aligned virtual address to map those pages to.
* - cpg = The number of pages to be mapped.
* - uiTableFlags = Flags to be used or verified for TTB entries.
* - uiPageFlags = Flags to be used for new page table entries.
* - uiAuxFlags = Flags to be used for new auxiliary TTB entries.
*
* Returns:
* TRUE if the mapping succeeded, FALSE if it failed.
*
* Side effects:
* May modify unallocated entries in the TTB. May modify any page tables that are pointed to by TTB entries,
* where applicable. If we need to allocate new page tables, may modify the global variables g_cpgForPageTables,
* g_ctblFreeonLastPage, and g_ptblNext.
*/
static BOOL map_pages(PHYSADDR paBase, KERNADDR vmaBase, INT32 cpg, UINT32 uiTableFlags,
UINT32 uiPageFlags, UINT32 uiAuxFlags)
{
static DECLARE_STRING8_CONST(sz1, "Map ");
static DECLARE_STRING8_CONST(sz2, "->");
static DECLARE_STRING8_CONST(sz3, ",cpg=");
static DECLARE_STRING8_CONST(sz4, ",tf=");
static DECLARE_STRING8_CONST(sz5, ",pf=");
static DECLARE_STRING8_CONST(sz6, ",af=");
INT32 ndxTTB = mmVMA2TTBIndex(vmaBase); /* TTB entry index */
INT32 ndxPage = mmVMA2PGTBLIndex(vmaBase); /* starting page entry index */
INT32 cpgCurrent; /* current number of pages mapped */
ETrWriteString8(sz1);
ETrWriteWord(paBase);
ETrWriteString8(sz2);
ETrWriteWord(vmaBase);
ETrWriteString8(sz3);
ETrWriteWord(cpg);
ETrWriteString8(sz4);
ETrWriteWord(uiTableFlags);
ETrWriteString8(sz5);
ETrWriteWord(uiPageFlags);
ETrWriteString8(sz6);
ETrWriteWord(uiAuxFlags);
ETrWriteChar8('\n');
if ((cpg > 0) && (ndxPage > 0))
{
/* We are starting in the middle of a VM page. Map to the end of the VM page. */
cpgCurrent = alloc_pages(paBase, g_pTTB + ndxTTB, g_pTTBAux + ndxTTB, ndxPage, cpg, uiTableFlags,
uiPageFlags, uiAuxFlags);
if (cpgCurrent < 0)
{
/* ETrWriteChar8('a'); */
return FALSE;
}
/* adjust base physical address, page count, and TTB index */
paBase += (cpgCurrent << SYS_PAGE_BITS);
cpg -= cpgCurrent;
ndxTTB++;
/* N.B.: from this point on ndxPage will be treated as 0 */
}
while (cpg >= SYS_PGTBL_ENTRIES)
{
/* try to map a whole section's worth at a time */
if ((paBase & TTBSEC_BASE) == paBase)
{
/* paBase is section-aligned now as well, we can use a direct 1Mb section mapping */
switch (g_pTTB[ndxTTB].data & TTBQUERY_MASK)
{
case TTBQUERY_FAULT: /* unmapped - map the section */
g_pTTB[ndxTTB].data = paBase | make_section_flags(uiTableFlags, uiPageFlags);
g_pTTBAux[ndxTTB].data = make_section_aux_flags(uiAuxFlags);
break;
case TTBQUERY_PGTBL: /* collided with a page table */
/* ETrWriteChar8('b'); */
return FALSE;
case TTBQUERY_SEC: /* test existing section */
case TTBQUERY_PXNSEC:
if ((g_pTTB[ndxTTB].data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags))
{
/* ETrWriteChar8('c'); */
return FALSE; /* invalid flags */
}
if (g_pTTBAux[ndxTTB].data != make_section_aux_flags(uiAuxFlags))
{
/* ETrWriteChar8('!'); */
return FALSE; /* invalid aux flags */
}
if ((g_pTTB[ndxTTB].data & TTBSEC_BASE) != paBase)
{
/* ETrWriteChar8('d'); */
return FALSE; /* invalid base address */
}
break;
}
cpgCurrent = SYS_PGTBL_ENTRIES; /* we mapped a whole section worth */
}
else
{
/* just map 256 individual pages */
cpgCurrent = alloc_pages(paBase, g_pTTB + ndxTTB, g_pTTBAux + ndxTTB, 0, cpg, uiTableFlags,
uiPageFlags, uiAuxFlags);
if (cpgCurrent < 0)
{
/* ETrWriteChar8('e'); */
return FALSE;
}
}
/* adjust base physical address, page count, and TTB index */
paBase += (cpgCurrent << SYS_PAGE_BITS);
cpg -= cpgCurrent;
ndxTTB++;
}
if (cpg > 0)
{
/* map the "tail end" onto the next TTB */
if (alloc_pages(paBase, g_pTTB + ndxTTB, g_pTTBAux + ndxTTB, 0, cpg, uiTableFlags, uiPageFlags, uiAuxFlags) < 0)
{
/* ETrWriteChar8('f'); */
return FALSE;
}
}
return TRUE;
}
/* External references to symbols defined by the linker script. */
extern char paFirstFree, cpgPrestartTotal, paLibraryCode, vmaLibraryCode, cpgLibraryCode, paKernelCode,
vmaKernelCode, cpgKernelCode, paKernelData, vmaKernelData, cpgKernelData, cpgKernelBss, paInitCode,
vmaInitCode, cpgInitCode, paInitData, vmaInitData, cpgInitData, cpgInitBss, vmaFirstFree;
/*
* Initializes a TTB (used as TTB1 and initially TTB0 as well) with mappings to all the pieces of the kernel and
* to memory-mapped IO, and fills in details in the startup info structure.
*
* Parameters:
* - pstartup - Pointer to startup info structure, which is modified by this function.
*
* Returns:
* - Physical address of the new TTB1.
*
* Side effects:
* Modifies physical memory beyond the end of the kernel to store TTB and page tables. Uses several
* static globals in this module for work space while performing memory mappings.
*/
PHYSADDR EMmInit(PSTARTUP_INFO pstartup)
{
static DECLARE_STRING8_CONST(szTTBAt, "EMmInit: TTB1@");
#if 0
static DECLARE_STRING8_CONST(szPageTable, "Page table pages:");
static DECLARE_STRING8_CONST(szFree, "\nFree last page:");
#endif
PHYSADDR paTTB = (PHYSADDR)(&paFirstFree); /* location of the system TTB1 */
UINT32 cbMPDB; /* number of bytes in the MPDB */
register INT32 i; /* loop counter */
/* Locate the appropriate place for TTB1, on a 16K boundary. */
pstartup->cpgTTBGap = 0;
while (paTTB & (SYS_TTB1_SIZE - 1))
{
paTTB += SYS_PAGE_SIZE;
pstartup->cpgTTBGap++;
}
ETrWriteString8(szTTBAt);
ETrWriteWord(paTTB);
ETrWriteChar8('\n');
/* Save off the TTB location and initialize it. */
pstartup->paTTB = paTTB;
g_pTTB = (PTTB)paTTB;
for (i=0; i<SYS_TTB1_ENTRIES; i++)
g_pTTB[i].data = 0;
/* Save off the TTB auxiliary data location and initialize it. */
pstartup->paTTBAux = paTTB + SYS_TTB1_SIZE;
g_pTTBAux = (PTTBAUX)(pstartup->paTTBAux);
for (i=0; i<SYS_TTB1_ENTRIES; i++)
g_pTTBAux[i].data = 0;
/* Allocate space for the Master Page Database but do not initialize it. */
pstartup->paMPDB = pstartup->paTTBAux + SYS_TTB1_SIZE;
cbMPDB = pstartup->cpgSystemTotal << 3; /* 8 bytes per entry */
pstartup->cpgMPDB = cbMPDB >> SYS_PAGE_BITS;
if (cbMPDB & (SYS_PAGE_SIZE - 1))
{
pstartup->cpgMPDB++;
cbMPDB = pstartup->cpgMPDB << SYS_PAGE_BITS;
}
/* Initialize the "next page table" pointer. */
pstartup->paFirstPageTable = pstartup->paMPDB + cbMPDB;
g_ptblNext = (PPAGETAB)(pstartup->paFirstPageTable);
g_cpgForPageTables = g_ctblFreeonLastPage = 0;
/* Map the "prestart" area (everything below load address, plus prestart code & data) as identity. */
VERIFY(map_pages(0, 0, (INT32)(&cpgPrestartTotal), TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01, 0));
/* Map the IO area as identity. */
VERIFY(map_pages(PHYSADDR_IO_BASE, PHYSADDR_IO_BASE, PAGE_COUNT_IO, TTBFLAGS_MMIO, PGTBLFLAGS_MMIO, 0));
/* Map the library area. */
VERIFY(map_pages((PHYSADDR)(&paLibraryCode), (KERNADDR)(&vmaLibraryCode), (INT32)(&cpgLibraryCode),
TTBFLAGS_LIB_CODE, PGTBLFLAGS_LIB_CODE, PGAUXFLAGS_LIB_CODE));
/* Map the kernel code area. */
VERIFY(map_pages((PHYSADDR)(&paKernelCode), (KERNADDR)(&vmaKernelCode), (INT32)(&cpgKernelCode),
TTBFLAGS_KERNEL_CODE, PGTBLFLAGS_KERNEL_CODE, PGAUXFLAGS_KERNEL_CODE));
/* Map the kernel data/BSS area. */
VERIFY(map_pages((PHYSADDR)(&paKernelData), (KERNADDR)(&vmaKernelData),
(INT32)(&cpgKernelData) + (INT32)(&cpgKernelBss), TTBFLAGS_KERNEL_DATA, PGTBLFLAGS_KERNEL_DATA,
PGAUXFLAGS_KERNEL_DATA));
/* Map the kernel init code area. */
VERIFY(map_pages((PHYSADDR)(&paInitCode), (KERNADDR)(&vmaInitCode), (INT32)(&cpgInitCode),
TTBFLAGS_INIT_CODE, PGTBLFLAGS_INIT_CODE, PGAUXFLAGS_INIT_CODE));
/* Map the kernel init data/BSS area. */
VERIFY(map_pages((PHYSADDR)(&paInitData), (KERNADDR)(&vmaInitData),
(INT32)(&cpgInitData) + (INT32)(&cpgInitBss), TTBFLAGS_INIT_DATA, PGTBLFLAGS_INIT_DATA,
PGAUXFLAGS_INIT_DATA));
/* Map the TTB itself. */
pstartup->kaTTB = (KERNADDR)(&vmaFirstFree);
VERIFY(map_pages(paTTB, pstartup->kaTTB, SYS_TTB1_SIZE / SYS_PAGE_SIZE, TTBFLAGS_KERNEL_DATA,
PGTBLFLAGS_KERNEL_DATA, PGAUXFLAGS_KERNEL_DATA));
/* Map the TTB auxiliary data. */
pstartup->kaTTBAux = pstartup->kaTTB + SYS_TTB1_SIZE;
VERIFY(map_pages(pstartup->paTTBAux, pstartup->kaTTBAux, SYS_TTB1_SIZE / SYS_PAGE_SIZE, TTBFLAGS_KERNEL_DATA,
PGTBLFLAGS_KERNEL_DATA, PGAUXFLAGS_KERNEL_DATA));
/* Map the Master Page Database. */
pstartup->kaMPDB = pstartup->kaTTBAux + SYS_TTB1_SIZE;
VERIFY(map_pages(pstartup->paMPDB, pstartup->kaTTB + SYS_TTB1_SIZE, pstartup->cpgMPDB, TTBFLAGS_KERNEL_DATA,
PGTBLFLAGS_KERNEL_DATA, PGAUXFLAGS_KERNEL_DATA));
/* Map the IO area into high memory as well. */
VERIFY(map_pages(PHYSADDR_IO_BASE, VMADDR_IO_BASE, PAGE_COUNT_IO, TTBFLAGS_MMIO, PGTBLFLAGS_MMIO, PGAUXFLAGS_MMIO));
/*
* Allocate one extra page table, just to ensure that we have sufficient free page table entries when we get up
* to the startup code.
*/
i = mmVMA2TTBIndex(VMADDR_KERNEL_FENCE);
while ((g_pTTB[i].data & TTBQUERY_MASK) != TTBQUERY_FAULT)
i++;
alloc_page_table(g_pTTB + i, g_pTTBAux + i, TTBFLAGS_KERNEL_DATA);
#if 0
/* Dump the TTB and page tables to trace output. */
ETrDumpWords((PUINT32)paTTB, (SYS_TTB1_SIZE + SYS_TTB1_SIZE + (g_cpgForPageTables << SYS_PAGE_BITS)) >> 2);
ETrWriteString8(szPageTable);
ETrWriteWord(g_cpgForPageTables);
ETrWriteString8(szFree);
ETrWriteWord(g_ctblFreeonLastPage);
ETrWriteChar8('\n');
#endif
/* Fill in the rest of the data in the startup info structure. */
pstartup->cpgPageTables = g_cpgForPageTables;
pstartup->ctblFreeOnLastPage = g_ctblFreeonLastPage;
pstartup->paFirstFree = pstartup->paFirstPageTable + (g_cpgForPageTables << SYS_PAGE_BITS);
pstartup->vmaFirstFree = pstartup->kaMPDB + cbMPDB;
return paTTB; /* return this for startup ASM code to use */
}

View File

@@ -0,0 +1,245 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#define __COMROGUE_PRESTART__
#include <comrogue/types.h>
#include <comrogue/internals/seg.h>
#include <comrogue/internals/llio.h>
#include <comrogue/internals/auxdev.h>
#include <comrogue/internals/gpio.h>
#include <comrogue/internals/16550.h>
#include <comrogue/internals/trace.h>
/* Hex digits. */
static DECLARE_STRING8_CONST(szHexDigits, "0123456789ABCDEF");
/*
* Initializes the trace functionality (the aux UART).
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Side effects:
* GPIO 14 configured for output from UART1; UART1 initialized to 115200 8N1 and enabled for output.
*/
void ETrInit(void)
{
register UINT32 ra;
/* Initialize UART */
llIOWrite(AUX_REG_ENABLE, AUX_ENABLE_MU); /* enable UART1 */
llIOWrite(AUX_MU_REG_IER, 0);
llIOWrite(AUX_MU_REG_CNTL, 0);
llIOWrite(AUX_MU_REG_LCR, U16550_LCR_LENGTH_8|U16550_LCR_PARITY_NONE); /* 8 bits, no parity */
llIOWrite(AUX_MU_REG_MCR, 0);
llIOWrite(AUX_MU_REG_IER, 0);
llIOWrite(AUX_MU_REG_FCR, U16550_FCR_RXCLEAR|U16550_FCR_TXCLEAR|U16550_FCR_LEVEL_14);
llIOWrite(AUX_MU_REG_BAUD, 270); /* 115200 baud */
ra = llIORead(GPFSEL1_REG);
ra &= ~GP_FUNC_MASK(4); /* GPIO 14 - connects to pin 8 on GPIO connector */
ra |= GP_FUNC_BITS(4, GP_PIN_ALT5); /* Alt function 5 - UART1 TxD */
llIOWrite(GPFSEL1_REG, ra);
llIOWrite(GPPUD_REG, 0);
llIODelay(150);
llIOWrite(GPPUDCLK0_REG, GP_BIT(14));
llIODelay(150);
llIOWrite(GPPUDCLK0_REG, 0);
llIOWrite(AUX_MU_REG_CNTL, AUXMU_CNTL_TXENABLE);
}
/*
* Writes a raw character to trace output.
*
* Parameters:
* - c = The character to be written.
*
* Returns:
* Nothing.
*
* Side effects:
* Character written to UART1.
*/
static void write_trace(UINT32 c)
{
register UINT32 lsr = llIORead(AUX_MU_REG_LSR);
while (!(lsr & U16550_LSR_TXEMPTY))
lsr = llIORead(AUX_MU_REG_LSR);
llIOWrite(AUX_MU_REG_THR, c);
}
/*
* Writes a character to trace output, translating newlines.
*
* Parameters:
* - c = The character to be written.
*
* Returns:
* Nothing.
*
* Side effects:
* Either 1 or 2 characters written to UART1.
*/
void ETrWriteChar8(CHAR c)
{
if (c == '\n')
write_trace('\r');
write_trace((UINT32)c);
}
/*
* Writes a null-terminated string to trace output. Newlines in the string are translated.
*
* Parameters:
* - psz = Pointer to string to be written.
*
* Returns:
* Nothing.
*
* Side effects:
* Characters in string written to UART1.
*/
void ETrWriteString8(PCSTR psz)
{
while (*psz)
ETrWriteChar8(*psz++);
}
/*
* Writes the value of a 32-bit word to trace output.
*
* Parameters:
* - uiValue = Value to be written to trace output.
*
* Returns:
* Nothing.
*
* Side effects:
* 8 characters written to UART1.
*/
void ETrWriteWord(UINT32 uiValue)
{
register UINT32 uiShift = 32;
do
{
uiShift -= 4;
write_trace(szHexDigits[(uiValue >> uiShift) & 0xF]);
} while (uiShift > 0);
}
/*
* Dumps the values of memory words beginning at a specified address.
*
* Parameters:
* - puiWords = Pointer to words to be dumped.
* - cWords = Number of words to be dumped.
*
* Returns:
* Nothing.
*
* Side effects:
* Many characters written to UART1.
*/
void ETrDumpWords(PUINT32 puiWords, UINT32 cWords)
{
static DECLARE_STRING8_CONST(szSpacer1, ": ");
register UINT32 i;
for (i = 0; i < cWords; i++)
{
if ((i & 0x3) == 0)
{
ETrWriteWord((UINT32)(puiWords + i));
ETrWriteString8(szSpacer1);
}
ETrWriteWord(puiWords[i]);
if ((i & 0x3) == 0x3)
ETrWriteChar8('\n');
else
ETrWriteChar8(' ');
}
if ((cWords & 0x3) != 0)
ETrWriteChar8('\n');
}
/*
* Prints an "assertion failed" message to trace output.
*
* Parameters:
* - pszFile = The file name the assertion was declared in.
* - nLine = The line number the assertion was declared at.
*
* Returns:
* Nothing.
*
* Side effects:
* Characters written to UART1.
*/
void ETrAssertFailed(PCSTR pszFile, INT32 nLine)
{
static DECLARE_STRING8_CONST(szPrefix, "** ASSERTION FAILED: ");
ETrWriteString8(szPrefix);
ETrWriteString8(pszFile);
write_trace(':');
ETrWriteWord((UINT32)nLine);
ETrWriteChar8('\n');
}
/*
* Puts the CPU into a loop where it blinks the green ACTIVITY light forever.
*
* Parameters:
* None.
*
* Returns:
* DOES NOT RETURN!
*
* Side effects:
* GPIO 16 configured for output and turns on and off indefinitely.
*/
void ETrInfiniBlink(void)
{
register UINT32 ra;
ra = llIORead(GPFSEL1_REG);
ra &= GP_FUNC_MASK(6); /* GPIO 16 - connects to green ACTIVITY LED */
ra |= GP_FUNC_BITS(6, GP_PIN_OUTPUT); /* output in all circumstances */
llIOWrite(GPFSEL1_REG, ra);
for(;;)
{
llIOWrite(GPSET0_REG, GP_BIT(16));
llIODelay(0x100000);
llIOWrite(GPCLR0_REG, GP_BIT(16));
llIODelay(0x100000);
}
}

View File

@@ -0,0 +1,177 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
/* Copied from default linker script for relocatable linking under ARM & modified */
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SECTIONS
{
/* Read-only sections, merged into text segment: */
.interp 0 : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash 0 : { *(.hash) }
.gnu.hash 0 : { *(.gnu.hash) }
.dynsym 0 : { *(.dynsym) }
.dynstr 0 : { *(.dynstr) }
.gnu.version 0 : { *(.gnu.version) }
.gnu.version_d 0: { *(.gnu.version_d) }
.gnu.version_r 0: { *(.gnu.version_r) }
.rel.init 0 : { *(.rel.init) }
.rela.init 0 : { *(.rela.init) }
.rel.text 0 : { *(.rel.text) }
.rela.text 0 : { *(.rela.text) }
.rel.fini 0 : { *(.rel.fini) }
.rela.fini 0 : { *(.rela.fini) }
.rel.rodata 0 : { *(.rel.rodata) }
.rela.rodata 0 : { *(.rela.rodata) }
.rel.data.rel.ro 0 : { *(.rel.data.rel.ro) }
.rela.data.rel.ro 0 : { *(.rela.data.rel.ro) }
.rel.data 0 : { *(.rel.data) *(.rel.bss) }
.rela.data 0 : { *(.rela.data) *(.rela.bss) }
.rel.tdata 0 : { *(.rel.tdata) *(.rel.tbss) }
.rela.tdata 0 : { *(.rela.tdata) *(.rela.tbss) }
.rel.ctors 0 : { *(.rel.ctors) }
.rela.ctors 0 : { *(.rela.ctors) }
.rel.dtors 0 : { *(.rel.dtors) }
.rela.dtors 0 : { *(.rela.dtors) }
.rel.got 0 : { *(.rel.got) }
.rela.got 0 : { *(.rela.got) }
.rel.iplt 0 :
{
*(.rel.iplt)
}
.rela.iplt 0 :
{
*(.rela.iplt)
}
.rel.plt 0 :
{
*(.rel.plt)
}
.rela.plt 0 :
{
*(.rela.plt)
}
.init 0 :
{
KEEP (*(.init))
} =0
.plt 0 : { *(.plt) }
.iplt 0 : { *(.iplt) }
.first.prestart.text 0 : { *(.first.text) }
.prestart.text 0 :
{
*(.text .stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0
.fini 0 :
{
KEEP (*(.fini))
} =0
.prestart.rodata 0 : { *(.rodata) }
.prestart.rodata1 0 : { *(.rodata1) }
.ARM.extab 0 : { *(.ARM.extab) }
.ARM.exidx 0 : { *(.ARM.exidx) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame 0 : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table 0 : ONLY_IF_RO { *(.gcc_except_table
.gcc_except_table.*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges 0 : ONLY_IF_RO { *(.exception_ranges
.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
/* Exception handling */
.eh_frame 0 : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table 0 : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges 0 : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
/* Thread Local Storage sections */
.tdata 0 : { *(.tdata) *(.tbss) }
.preinit_array 0 :
{
KEEP (*(.preinit_array))
}
.jcr 0 : { KEEP (*(.jcr)) }
.dynamic 0 : { *(.dynamic) }
.got 0 : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
.prestart.data 0 :
{
*(.data)
*(.dynbss)
*(.bss)
*(COMMON)
}
.prestart.data1 0 : { *(.data1) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
.stack 0 :
{
*(.stack)
}
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
}

271
kernel/prestart/prestart.S Normal file
View File

@@ -0,0 +1,271 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#define __COMROGUE_PRESTART__
#include <comrogue/internals/asm-macros.h>
#include <comrogue/internals/layout.h>
#include <comrogue/internals/mmu.h>
#include <comrogue/internals/sctlr.h>
/*------------------------------------------------------------------------------------------
* The prestart code that gets control when the kernel is first loaded; its objective is to
* set up the MMU and hand over control to the actual start code.
*------------------------------------------------------------------------------------------
*/
.section ".first.text"
.globl COMROGUEPrestart
/* On entry: r0 = 0, r1 = machine type, r2 = atags address */
COMROGUEPrestart:
/* Initialize a temporary stack area. */
mov ip, # PHYSADDR_LOAD
sub sp, ip, #4
/* Go collect the startup info. */
bl KiCollectStartupInfo
mov r11, r0 /* r11 = address of startup info structure */
/* at this point r0-r2 are free for other code to use */
/* Early trace initialize; we reinitialize it later. */
bl ETrInit
ldr r0, =.initMessage
bl ETrWriteString8
/* Copy the early vector table into place, including the vector words that live after the table itself. */
ldr r0, =.earlyVectorTable
ldr r1, =.earlyVectorTableEnd
mov r2, #0
b .vec1
.vec0:
ldm r0!, {r3-r6} /* copy 16 bytes at a time */
stm r2!, {r3-r6}
.vec1:
cmp r0, r1
bne .vec0
/* Initialize early memory management (the TTB1). */
mov r0, r11
bl EMmInit
mov r10, r0 /* r10 = address of TTB */
/* Set up and start the MMU. */
mov ip, #0
mcr p15, 0, ip, c7, c7, 0 /* clear caches */
mcr p15, 0, ip, c8, c7, 0 /* clear TLB */
mov ip, #1
mcr p15, 0, ip, c2, c0, 2 /* set TTBCR */
mvn ip, #0
mcr p15, 0, ip, c3, c0, 0 /* configure domain 0 = client, all others = invalid */
mcr p15, 0, r10, c2, c0, 0 /* set TTB0 */
mcr p15, 0, r10, c2, c0, 1 /* set TTB1 */
mrc p15, 0, ip, c1, c0, 0 /* get control register 1 */
orr ip, ip, # SCTLR_M /* MMU = on */
orr ip, ip, # SCTLR_XP /* subpage AP bits disabled in 2nd-level page tables */
instr_barrier
mcr p15, 0, ip, c1, c0, 0 /* store control register 1 */
mrc p15, 0, ip, c0, c0, 0 /* read ID register */
instr_barrier
#if 0
ldr r0, =.msg1
bl ETrWriteString8
#endif
/* now go to the start area in kernel space */
mov r0, r11
ldr ip, =COMROGUEStart
mov pc, ip
#if 0
.balign 4
.msg1:
.asciz "got here 1\n"
.balign 4
#endif
/*-------------------------------------------------------------
* Early exception-handler code, mainly for debugging purposes
*-------------------------------------------------------------
*/
.earlyReset:
ldr r0, =.resetMessage
b .earlyFUBAR
.earlyUndef:
ldr r0, =.undefMessage
b .earlyFUBAR
.earlySVC:
ldr r0, =.svcMessage
b .earlyFUBAR
.earlyPrefetch:
ldr r0, =.prefetchMessage
b .earlyFUBAR
.earlyData:
ldr r0, =.dataMessage
b .earlyFUBAR
.earlyHyp:
ldr r0, =.hypMessage
b .earlyFUBAR
.earlyIRQ:
ldr r0, =.irqMessage
b .earlyFUBAR
.earlyFIQ:
ldr r0, =.fiqMessage
.earlyFUBAR:
bl ETrWriteString8
.hang:
wfe
b .hang
.earlyVectorTable:
ldr pc, .resetVector
ldr pc, .undefVector
ldr pc, .svcVector
ldr pc, .prefetchVector
ldr pc, .dataVector
ldr pc, .hypVector
ldr pc, .irqVector
ldr pc, .fiqVector
.resetVector:
.word .earlyReset
.undefVector:
.word .earlyUndef
.svcVector:
.word .earlySVC
.prefetchVector:
.word .earlyPrefetch
.dataVector:
.word .earlyData
.hypVector:
.word .earlyHyp
.irqVector:
.word .earlyIRQ
.fiqVector:
.word .earlyFIQ
.earlyVectorTableEnd:
.balign 4
.initMessage:
.asciz "COMROGUEPrestart\n"
.balign 4
.resetMessage:
.asciz "+++ RESET!!!\n"
.balign 4
.undefMessage:
.asciz "+++ UNDEF!!!\n"
.balign 4
.svcMessage:
.asciz "+++ SVC!!!\n"
.balign 4
.prefetchMessage:
.asciz "+++ PREFETCH!!!\n"
.balign 4
.dataMessage:
.asciz "+++ DATA!!!\n"
.balign 4
.hypMessage:
.asciz "+++ HYP!!!\n"
.balign 4
.irqMessage:
.asciz "+++ IRQ!!!\n"
.balign 4
.fiqMessage:
.asciz "+++ FIQ!!!\n"
/*--------------------------------------------------------------------------------------
* Low-level IO functions that are placed here to make them callable from prestart code
*--------------------------------------------------------------------------------------
*/
.section ".text"
/*
* Writes a 32-bit word of data to a memory-mapped IO port.
*
* Parameters:
* - paPort = Physical address of the IO port to write to.
* - uiData = Data to be written.
*
* Returns:
* Nothing.
*
* Side effects:
* Writing to any given IO port may have arbitrary side effects.
*/
.globl llIOWritePA
llIOWritePA:
str r1,[r0]
bx lr
/*
* Reads a 32-bit word of data from a memory-mapped IO port.
*
* Parameters:
* - paPort = Physical address of the IO port we read from.
*
* Returns:
* The word of data read from the IO port.
*
* Side effects:
* Reading from any given IO port may have arbitrary side effects.
*/
.globl llIOReadPA
llIOReadPA:
ldr r0,[r0]
bx lr
/*
* Delays for a certain number of cycles, to allow an IO operation to work.
*
* Parameters:
* - uiTicks = The number of "ticks" to delay.
*
* Returns:
* Nothing.
*/
.globl llIODelayPA
llIODelayPA:
push {lr}
.delaytop:
nop
nop
bl .delayreturn
nop
nop
subs r0, r0, #1
bne .delaytop
pop {lr}
.delayreturn:
bx lr