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:
43
kernel/prestart/Makefile
Normal file
43
kernel/prestart/Makefile
Normal 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
|
||||
247
kernel/prestart/collect_startup.c
Normal file
247
kernel/prestart/collect_startup.c
Normal 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
472
kernel/prestart/early_mm.c
Normal 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 */
|
||||
}
|
||||
245
kernel/prestart/early_trace.c
Normal file
245
kernel/prestart/early_trace.c
Normal 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);
|
||||
}
|
||||
}
|
||||
177
kernel/prestart/kernel-prestart.ldi
Normal file
177
kernel/prestart/kernel-prestart.ldi
Normal 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
271
kernel/prestart/prestart.S
Normal 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
|
||||
Reference in New Issue
Block a user