From 54529bc017e7f8a6a4b41810171b8f7d457b837c Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Sun, 14 Apr 2013 03:38:48 -0600 Subject: [PATCH] started in on a bunch of memory management code --- idl/comrogue/allocator.idl | 19 + idl/comrogue/object_types.idl | 3 + idl/comrogue/objectbase.idl | 13 + include/comrogue/internals/memmgr.h | 61 +++ include/comrogue/internals/mmu.h | 18 +- include/comrogue/object_definition_macros.h | 41 +- include/comrogue/objhelp.h | 56 +++ include/comrogue/scode.h | 35 +- include/comrogue/stdobj.h | 51 +++ include/comrogue/str.h | 4 +- kernel/Makefile | 6 +- kernel/early_mm.c | 28 +- kernel/init_heap.c | 308 +++++++++++++ kernel/lib_guids.c | 50 +++ kernel/memmgr.c | 49 +++ kernel/objhelp.c | 93 ++++ kernel/pagealloc.c | 58 +++ kernel/sizes.h | 43 ++ kernel/start.S | 7 +- kernel/strcomparemem.S | 187 ++++++++ kernel/strcopymem.S | 4 +- kernel/strsetmem.S | 183 ++++++++ kernel/vmmap.c | 465 ++++++++++++++++++++ 23 files changed, 1741 insertions(+), 41 deletions(-) create mode 100644 idl/comrogue/allocator.idl create mode 100644 include/comrogue/internals/memmgr.h create mode 100644 include/comrogue/objhelp.h create mode 100644 include/comrogue/stdobj.h create mode 100644 kernel/init_heap.c create mode 100644 kernel/lib_guids.c create mode 100644 kernel/memmgr.c create mode 100644 kernel/objhelp.c create mode 100644 kernel/pagealloc.c create mode 100644 kernel/sizes.h create mode 100644 kernel/strcomparemem.S create mode 100644 kernel/strsetmem.S create mode 100644 kernel/vmmap.c diff --git a/idl/comrogue/allocator.idl b/idl/comrogue/allocator.idl new file mode 100644 index 0000000..e138c6f --- /dev/null +++ b/idl/comrogue/allocator.idl @@ -0,0 +1,19 @@ +import "comrogue/objectbase.idl"; + +/*------------------- + * IMalloc interface + *------------------- + */ + +[object, uuid(00000002-0000-0000-C000-000000000046)] +interface IMalloc : IUnknown +{ + [unique] typedef IMalloc *PMALLOC; + PVOID Alloc([in] SIZE_T cb); + PVOID Realloc([in] PVOID pv, [in] SIZE_T cb); + void Free([in] PVOID pv); + SIZE_T GetSize([in] PVOID pv); + INT32 DidAlloc([in] PVOID pv); + void HeapMinimize(void); +} + diff --git a/idl/comrogue/object_types.idl b/idl/comrogue/object_types.idl index 8430936..7d5ef6d 100644 --- a/idl/comrogue/object_types.idl +++ b/idl/comrogue/object_types.idl @@ -49,6 +49,9 @@ interface ICOMROGUETypes typedef INT32 INT_PTR; typedef UINT32 UINT_PTR; + typedef UINT_PTR SIZE_T; + typedef INT_PTR SSIZE_T; + /* Base pointer type definitions */ typedef INT16 *PINT16; typedef UINT16 *PUINT16; diff --git a/idl/comrogue/objectbase.idl b/idl/comrogue/objectbase.idl index 077d745..dfd462c 100644 --- a/idl/comrogue/objectbase.idl +++ b/idl/comrogue/objectbase.idl @@ -45,6 +45,19 @@ interface IUnknown UINT32 Release(); } +/*------------------------- + * IClassFactory interface + *------------------------- + */ + +[object, uuid(00000001-0000-0000-C000-000000000046), pointer_default(unique)] +interface IClassFactory : IUnknown +{ + [unique] typedef IClassFactory *PCLASSFACTORY; + HRESULT CreateInstance([in, unique] IUnknown *punkOuter, [in] REFIID riid, [out, iid_is(riid)] PPVOID ppvObject); + HRESULT LockServer([in] BOOL fLock); +} + /*---------------------------- * IServiceProvider interface *---------------------------- diff --git a/include/comrogue/internals/memmgr.h b/include/comrogue/internals/memmgr.h new file mode 100644 index 0000000..0f65bc0 --- /dev/null +++ b/include/comrogue/internals/memmgr.h @@ -0,0 +1,61 @@ +/* + * 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. + */ +#ifndef __MEMMGR_H_INCLUDED +#define __MEMMGR_H_INCLUDED + +#ifdef __COMROGUE_INTERNALS__ + +#ifndef __ASM__ + +#include +#include +#include +#include + +CDECL_BEGIN + +/* Page mapping functions */ +extern PHYSADDR MmGetPhysAddr(PTTB pTTB, KERNADDR vma); +extern HRESULT MmDemapPages(PTTB pTTB, KERNADDR vmaBase, UINT32 cpg); +extern HRESULT MmMapPages(PTTB pTTB, PHYSADDR paBase, KERNADDR vmaBase, UINT32 cpg, UINT32 uiTableFlags, + UINT32 uiPageFlags); + +/* Initialization functions only */ +extern void _MmInit(PSTARTUP_INFO pstartup); + +CDECL_END + +#endif /* __ASM__ */ + +#endif /* __COMROGUE_INTERNALS__ */ + +#endif /* __MEMMGR_H_INCLUDED */ diff --git a/include/comrogue/internals/mmu.h b/include/comrogue/internals/mmu.h index bbaba99..7bf3a64 100644 --- a/include/comrogue/internals/mmu.h +++ b/include/comrogue/internals/mmu.h @@ -43,6 +43,7 @@ #define SYS_PAGE_SIZE 4096 /* standard page size for normal page */ #define SYS_PAGE_BITS 12 /* log2(SYS_PAGE_SIZE), number of bits in a page address */ #define SYS_TTB0_SIZE 8192 /* TTB0 must be located on this boundary and is this size */ +#define SYS_TTB0_ENTRIES 2048 /* SYS_TTB0_SIZE/4, number of entries in TTB0 */ #define SYS_TTB1_SIZE 16384 /* TTB1 must be located on this boundary and is this size */ #define SYS_TTB1_ENTRIES 4096 /* SYS_TTB1_SIZE/4, number of entries in TTB1 */ #define SYS_TTB_BITS 12 /* log2(SYS_TTB1_SIZE/4), number of bits in a TTB address */ @@ -124,6 +125,16 @@ #define PGQUERY_SM 0x00000002 /* small page (4K) */ #define PGQUERY_SM_XN 0x00000003 /* small page with Execute-Never set */ +/* Combinations of flags we use regularly. */ +#define TTBFLAGS_LIB_CODE TTBPGTBL_ALWAYS +#define PGTBLFLAGS_LIB_CODE (PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP10) +#define TTBFLAGS_KERNEL_CODE TTBPGTBL_ALWAYS +#define PGTBLFLAGS_KERNEL_CODE (PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01) +#define TTBFLAGS_KERNEL_DATA TTBPGTBL_ALWAYS +#define PGTBLFLAGS_KERNEL_DATA (PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01) +#define TTBFLAGS_MMIO TTBPGTBL_ALWAYS +#define PGTBLFLAGS_MMIO (PGTBLSM_ALWAYS | PGTBLSM_AP01) + #ifndef __ASM__ /*------------------------------------------------------- @@ -224,16 +235,21 @@ typedef struct tagPAGETAB { /* internal structure of a MPDB entry */ typedef struct tagMPDB1 { + PHYSADDR paPTE; /* PA of page table entry for the page */ unsigned next : 20; /* index of "next" entry in list */ unsigned tag : 12; /* page tag */ } MPDB1; /* The MPDB entry itself. */ typedef union tagMPDB { - UINT32 raw; /* raw data */ + UINT64 raw; /* raw data */ MPDB1 d; /* structured data */ } MPDB, *PMPDB; +/* Page index macros */ +#define mmPA2PageIndex(pa) ((pa) >> SYS_PAGE_BITS) +#define mmPageIndex2PA(ndx) ((ndx) << SYS_PAGE_BITS) + #endif /* __ASM__ */ #endif /* __COMROGUE_INTERNALS__ */ diff --git a/include/comrogue/object_definition_macros.h b/include/comrogue/object_definition_macros.h index b8daf5c..fb955f1 100644 --- a/include/comrogue/object_definition_macros.h +++ b/include/comrogue/object_definition_macros.h @@ -1,3 +1,34 @@ +/* + * 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. + */ #ifndef __OBJECT_DEFINITION_MACROS_H_INCLUDED #define __OBJECT_DEFINITION_MACROS_H_INCLUDED @@ -28,7 +59,7 @@ #else #define DEFINE_UUID_TYPE(typ, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - EXTERN_C extern const typ GUIDATTR name + EXTERN_C extern const typ name #endif /* INITGUID */ @@ -61,11 +92,11 @@ #define INHERIT_METHODS(sym) sym #define BEGIN_INTERFACE(typ) \ + struct typ ## VTable; \ + typedef interface tagIf ## typ { const struct typ ## VTable *pVTable; } typ; \ struct typ ## VTable { -#define BEGIN_INTERFACE_(typ, parent) \ - struct typ ## VTable { -#define END_INTERFACE(typ) }; \ - typedef interface typ { const struct typ ## VTable *pVTable; } typ; +#define BEGIN_INTERFACE_(typ, parent) BEGIN_INTERFACE(typ) +#define END_INTERFACE(typ) }; #else diff --git a/include/comrogue/objhelp.h b/include/comrogue/objhelp.h new file mode 100644 index 0000000..a5cd84d --- /dev/null +++ b/include/comrogue/objhelp.h @@ -0,0 +1,56 @@ +/* + * 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. + */ +#ifndef __OBJHELP_H_INCLUDED +#define __OBJHELP_H_INCLUDED + +#ifndef __ASM__ + +#include +#include +#include + +CDECL_BEGIN + +/* QueryInterface helpers */ +extern HRESULT ObjHlpStandardQueryInterface_IMalloc(IUnknown *pThis, REFIID riid, PPVOID ppvObject); + +/* AddRef/Release helpers */ +extern UINT32 ObjHlpStaticAddRefRelease(IUnknown *pThis); + +/* Other helpers */ +extern void ObjHlpDoNothingReturnVoid(IUnknown *pThis); + +CDECL_END + +#endif /* __ASM__ */ + +#endif /* __OBJHELP_H_INCLUDED */ diff --git a/include/comrogue/scode.h b/include/comrogue/scode.h index d00693b..5b6f579 100644 --- a/include/comrogue/scode.h +++ b/include/comrogue/scode.h @@ -58,6 +58,7 @@ #define FACILITY_ITF 4 #define FACILITY_COMROGUE 7 #define FACILITY_STRFORMAT 0x333 +#define FACILITY_MEMMGR 0x601 #ifndef __ASM__ @@ -79,19 +80,27 @@ #endif /* __ASM__ */ -#define S_OK SCODE_CAST(0x00000000) /* OK return */ -#define S_FALSE SCODE_CAST(0x00000001) /* "False" return */ +/* Basic success codes */ +#define S_OK SCODE_CAST(0x00000000) /* OK return */ +#define S_FALSE SCODE_CAST(0x00000001) /* "False" return */ -#define E_NOTIMPL SCODE_CAST(0x80000001) /* not implemented */ -#define E_OUTOFMEMORY SCODE_CAST(0x80000002) /* out of memory */ -#define E_INVALIDARG SCODE_CAST(0x80000003) /* invalid argument */ -#define E_NOINTERFACE SCODE_CAST(0x80000004) /* no such interface */ -#define E_POINTER SCODE_CAST(0x80000005) /* invalid pointer */ -#define E_HANDLE SCODE_CAST(0x80000006) /* invalid handle */ -#define E_ABORT SCODE_CAST(0x80000007) /* aborted operation */ -#define E_FAIL SCODE_CAST(0x80000008) /* unspecified failure */ -#define E_ACCESSDENIED SCODE_CAST(0x80000009) /* access denied */ -#define E_PENDING SCODE_CAST(0x8000000A) /* data not yet available */ -#define E_UNEXPECTED SCODE_CAST(0x8000FFFF) /* unexpected error */ +/* Basic error codes */ +#define E_NOTIMPL SCODE_CAST(0x80000001) /* not implemented */ +#define E_OUTOFMEMORY SCODE_CAST(0x80000002) /* out of memory */ +#define E_INVALIDARG SCODE_CAST(0x80000003) /* invalid argument */ +#define E_NOINTERFACE SCODE_CAST(0x80000004) /* no such interface */ +#define E_POINTER SCODE_CAST(0x80000005) /* invalid pointer */ +#define E_HANDLE SCODE_CAST(0x80000006) /* invalid handle */ +#define E_ABORT SCODE_CAST(0x80000007) /* aborted operation */ +#define E_FAIL SCODE_CAST(0x80000008) /* unspecified failure */ +#define E_ACCESSDENIED SCODE_CAST(0x80000009) /* access denied */ +#define E_PENDING SCODE_CAST(0x8000000A) /* data not yet available */ +#define E_UNEXPECTED SCODE_CAST(0x8000FFFF) /* unexpected error */ + +/* Memory manager error codes */ +#define MEMMGR_E_NOPGTBL SCODE_CAST(0x86010001) /* no page tables available */ +#define MEMMGR_E_BADTTBFLG SCODE_CAST(0x86010002) /* bad TTB flags encountered */ +#define MEMMGR_E_COLLIDED SCODE_CAST(0x86010003) /* memory mapping collided */ +#define MEMMGR_E_ENDTTB SCODE_CAST(0x86010004) /* tried to "walk off" end of TTB */ #endif /* __SCODE_H_INCLUDED */ diff --git a/include/comrogue/stdobj.h b/include/comrogue/stdobj.h new file mode 100644 index 0000000..3e4dda6 --- /dev/null +++ b/include/comrogue/stdobj.h @@ -0,0 +1,51 @@ +/* + * 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. + */ +#ifndef __STDOBJ_H_INCLUDED +#define __STDOBJ_H_INCLUDED + +#ifndef __ASM__ + +#include +#include + +CDECL_BEGIN + +extern BOOL IsEqualGUID(REFGUID guid1, REFGUID guid2); + +CDECL_END + +#define IsEqualIID(iid1, iid2) IsEqualGUID(iid1, iid2) +#define IsEqualCLSID(clsid1, clsid2) IsEqualGUID(clsid1, clsid2) + +#endif /* __ASM__ */ + +#endif /* __STDOBJ_H_INCLUDED */ diff --git a/include/comrogue/str.h b/include/comrogue/str.h index 8e9bc48..bc01c55 100644 --- a/include/comrogue/str.h +++ b/include/comrogue/str.h @@ -48,7 +48,9 @@ typedef HRESULT (*PFNFORMAT8)(PPVOID, PCCHAR, UINT32); CDECL_BEGIN -extern PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, INT32 nBytes); +extern PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, SSIZE_T cb); +extern INT32 StrCompareMem(PCVOID pMem1, PCVOID pMem2, SSIZE_T cb); +extern PVOID StrSetMem(PVOID pMem, INT32 ch, SSIZE_T cb); extern BOOL StrIsDigit8(CHAR ch); extern INT32 StrLength8(PCSTR psz); diff --git a/kernel/Makefile b/kernel/Makefile index 9f54039..26eddd0 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -48,9 +48,9 @@ AFLAGS = -mcpu=arm1176jzf-s -mfloat-abi=hard ASM_CPP_FLAGS = $(INCLUDES) $(DEFS) -D__ASM__ PRESTART_OBJS = prestart.o early_trace.o collect_startup.o early_mm.o -LIB_OBJS = divide.o qdivrem.o intlib.o str.o strcopymem.o -RES_OBJS = lowlevel.o trace.o -INIT_OBJS = start.o kistart.o +LIB_OBJS = divide.o qdivrem.o intlib.o objhelp.o str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o +RES_OBJS = lowlevel.o trace.o memmgr.o vmmap.o pagealloc.o +INIT_OBJS = start.o kistart.o init_heap.o all: kernel.img diff --git a/kernel/early_mm.c b/kernel/early_mm.c index 98be926..cc9fced 100644 --- a/kernel/early_mm.c +++ b/kernel/early_mm.c @@ -99,7 +99,7 @@ SEG_INIT_CODE static UINT32 make_section_flags(UINT32 uiTableFlags, UINT32 uiPag * 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 ndxTTB'th entry in the TTB, if it was not previously allocated. May modify the current page + * 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. */ @@ -334,7 +334,7 @@ SEG_INIT_CODE PHYSADDR EMmInit(PSTARTUP_INFO pstartup) /* Allocate space for the Master Page Database but do not initialize it. */ pstartup->paMPDB = paTTB + SYS_TTB1_SIZE; - cbMPDB = pstartup->cpgSystemTotal << 2; + cbMPDB = pstartup->cpgSystemTotal << 3; /* 8 bytes per entry */ pstartup->cpgMPDB = cbMPDB >> SYS_PAGE_BITS; if (cbMPDB & (SYS_PAGE_SIZE - 1)) { @@ -349,34 +349,32 @@ SEG_INIT_CODE PHYSADDR EMmInit(PSTARTUP_INFO pstartup) /* 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)); /* Map the IO area as identity. */ - VERIFY(map_pages(PHYSADDR_IO_BASE, PHYSADDR_IO_BASE, PAGE_COUNT_IO, TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01)); + VERIFY(map_pages(PHYSADDR_IO_BASE, PHYSADDR_IO_BASE, PAGE_COUNT_IO, TTBFLAGS_MMIO, PGTBLFLAGS_MMIO)); /* Map the library area. */ VERIFY(map_pages((PHYSADDR)(&paLibraryCode), (KERNADDR)(&vmaLibraryCode), (INT32)(&cpgLibraryCode), - TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP10)); + TTBFLAGS_LIB_CODE, PGTBLFLAGS_LIB_CODE)); /* Map the kernel code area. */ VERIFY(map_pages((PHYSADDR)(&paKernelCode), (KERNADDR)(&vmaKernelCode), (INT32)(&cpgKernelCode), - TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)); + TTBFLAGS_KERNEL_CODE, PGTBLFLAGS_KERNEL_CODE)); /* Map the kernel data/BSS area. */ VERIFY(map_pages((PHYSADDR)(&paKernelData), (KERNADDR)(&vmaKernelData), - (INT32)(&cpgKernelData) + (INT32)(&cpgKernelBss), - TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)); + (INT32)(&cpgKernelData) + (INT32)(&cpgKernelBss), TTBFLAGS_KERNEL_DATA, PGTBLFLAGS_KERNEL_DATA)); /* Map the kernel init code area. */ VERIFY(map_pages((PHYSADDR)(&paInitCode), (KERNADDR)(&vmaInitCode), (INT32)(&cpgInitCode), - TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)); + TTBFLAGS_KERNEL_CODE, PGTBLFLAGS_KERNEL_CODE)); /* Map the kernel init data/BSS area. */ VERIFY(map_pages((PHYSADDR)(&paInitData), (KERNADDR)(&vmaInitData), - (INT32)(&cpgInitData) + (INT32)(&cpgInitBss), - TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)); + (INT32)(&cpgInitData) + (INT32)(&cpgInitBss), TTBFLAGS_KERNEL_DATA, PGTBLFLAGS_KERNEL_DATA)); /* Map the TTB itself. */ pstartup->kaTTB = (KERNADDR)(&vmaFirstFree); - VERIFY(map_pages(paTTB, pstartup->kaTTB, SYS_TTB1_SIZE / SYS_PAGE_SIZE, - TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)); + VERIFY(map_pages(paTTB, pstartup->kaTTB, SYS_TTB1_SIZE / SYS_PAGE_SIZE, TTBFLAGS_KERNEL_DATA, + PGTBLFLAGS_KERNEL_DATA)); /* Map the Master Page Database. */ pstartup->kaMPDB = pstartup->kaTTB + SYS_TTB1_SIZE; - VERIFY(map_pages(pstartup->paMPDB, pstartup->kaTTB + SYS_TTB1_SIZE, pstartup->cpgMPDB, - TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)); + VERIFY(map_pages(pstartup->paMPDB, pstartup->kaTTB + SYS_TTB1_SIZE, pstartup->cpgMPDB, TTBFLAGS_KERNEL_DATA, + PGTBLFLAGS_KERNEL_DATA)); /* Map the IO area into high memory as well. */ - VERIFY(map_pages(PHYSADDR_IO_BASE, VMADDR_IO_BASE, PAGE_COUNT_IO, TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01)); + VERIFY(map_pages(PHYSADDR_IO_BASE, VMADDR_IO_BASE, PAGE_COUNT_IO, TTBFLAGS_MMIO, PGTBLFLAGS_MMIO)); #if 0 /* Dump the TTB and page tables to trace output. */ diff --git a/kernel/init_heap.c b/kernel/init_heap.c new file mode 100644 index 0000000..f5d3f86 --- /dev/null +++ b/kernel/init_heap.c @@ -0,0 +1,308 @@ +/* + * 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. + */ +#include +#include +#include +#include +#include +#include "sizes.h" + +/*------------------------------------------------------------------------------------------------------------- + * Initial heap implementation. Since this will only be used by initializer code and freed with the rest + * of the initializer code and data, it doesn't need to be very efficient. The implementation is adapted from + * the original K&R storage allocator, with modifications to implement the full IMalloc interface. + *------------------------------------------------------------------------------------------------------------- + */ + +extern PCHAR g_pInitHeapBlock; /* pointer to heap init block defined in assembly code */ + +typedef union tagBLOCK +{ + struct + { + union tagBLOCK *pNextFree; /* pointer to next free block */ + SIZE_T cblk; /* size of this free block (in blocks) */ + } data; + INT64 x; /* to force alignment */ +} BLOCK, *PBLOCK; + +typedef struct tagINITHEAP +{ + IMalloc hdr; /* object header must be first */ + BLOCK blkBase; /* base "zero" block */ + PBLOCK pblkLastAlloc; /* last allocated block */ +} INITHEAP, *PINITHEAP; + +/* + * Allocates a block of memory. + * + * Parameters: + * - pThis = Base interface pointer. + * - cb = Size of the memory block to be allocated, in bytes. + * + * Returns: + * A pointer to the allocated block of memory, or NULL if memory could not be allocated. + */ +SEG_INIT_CODE static PVOID init_heap_Alloc(IMalloc *pThis, SIZE_T cb) +{ + PINITHEAP pih = (PINITHEAP)pThis; + register PBLOCK p, q; + register SIZE_T nBlocks = 1 + (cb + sizeof(BLOCK) - 1) / sizeof(BLOCK); + + q = pih->pblkLastAlloc; + for (p = q->data.pNextFree; ; q = p, p = p->data.pNextFree) + { + if (p->data.cblk >= nBlocks) + { + if (p->data.cblk == nBlocks) + q->data.pNextFree = p->data.pNextFree; + else + { + p->data.cblk -= nBlocks; + p += p->data.cblk; + p->data.cblk = nBlocks; + } + pih->pblkLastAlloc = q; + return (PVOID)(p + 1); + } + if (p == pih->pblkLastAlloc) + break; + } + return NULL; +} + +/* + * Determines whether this allocator was used to allocate a block of memory. + * + * Parameters: + * - pThis = Base interface pointer. + * - pv = Pointer to the memory block to test. If this parameter is NULL, -1 is returned. + * + * Returns: + * - 1 = If the memory block was allocated by this allocator. + * - 0 = If the memory block was not allocated by this allocator. + * - -1 = If this method cannot determine whether the allocator allocated the memory block. + */ +SEG_INIT_CODE static INT32 init_heap_DidAlloc(IMalloc *pThis, PVOID pv) +{ + register PCHAR p = (PCHAR)pv; + if (!pv) + return -1; /* not our business */ + return ((p >= g_pInitHeapBlock) && (p < g_pInitHeapBlock + SIZE_INIT_HEAP)) ? 1 : 0; +} + +/* + * Frees a previously allocated block of memory. + * + * Parameters: + * - pThis = Base interface pointer. + * - pv = Pointer to the memory block to be freed. If this parameter is NULL, this method has no effect. + * + * Returns: + * Nothing. + * + * Side effects: + * After this call, the memory pointed to by pv is invalid and should not be used. + */ +SEG_INIT_CODE static void init_heap_Free(IMalloc *pThis, PVOID pv) +{ + PINITHEAP pih = (PINITHEAP)pThis; + register PBLOCK p, q; + + if (init_heap_DidAlloc(pThis, pv) != 1) + return; /* not our business */ + p = ((PBLOCK)pv) - 1; + for (q = pih->pblkLastAlloc; !((p > q) && (p < q->data.pNextFree)); q = q->data.pNextFree) + if ((q >= q->data.pNextFree) && ((p > q) || (p < q->data.pNextFree))) + break; /* at one end or another */ + if (p + p->data.cblk == q->data.pNextFree) + { + /* coalesce block with next (free) block */ + p->data.cblk += q->data.pNextFree->data.cblk; + p->data.pNextFree = q->data.pNextFree->data.pNextFree; + } + else + p->data.pNextFree = q->data.pNextFree; /* chain to next free block */ + if (q + q->data.cblk == p) + { + /* coalesce free block with previous (free) block */ + q->data.cblk += p->data.cblk; + q->data.pNextFree = p->data.pNextFree; + } + else + q->data.pNextFree = p; /* chain to previous free block */ + pih->pblkLastAlloc = q; +} + +/* + * Changes the size of a previously allocated block. + * + * Parameters: + * - pThis = Base interface pointer. + * - pv = Pointer to the block of memory to be reallocated. If this parameter is NULL, a block of memory + * of size cb is allocated and returned. + * - cb = The new size of the memory block to be reallocated, in bytes. If this parameter is 0 and pv is + * not NULL, the block of memory pointed to by pv is freed and NULL is returned. + * + * Returns: + * If pv is not NULL and cb is 0, NULL is always returned. Otherwise, NULL is returned if the block of memory + * could not be reallocated, or the pointer to the reallocated block of memory is returned. + */ +SEG_INIT_CODE static PVOID init_heap_Realloc(IMalloc *pThis, PVOID pv, SIZE_T cb) +{ + PINITHEAP pih = (PINITHEAP)pThis; + SIZE_T nBlocksNew, nBlocksExtra; + PVOID pNew; + register PBLOCK p, pNext, q, qp; + + /* Handle degenerate cases */ + if (!pv) + return init_heap_Alloc(pThis, cb); + if (cb == 0) + { + init_heap_Free(pThis, pv); + return NULL; + } + if (init_heap_DidAlloc(pThis, pv) != 1) + return NULL; /* not our business */ + + p = ((PBLOCK)pv) - 1; + nBlocksNew = 1 + (cb + sizeof(BLOCK) - 1) / sizeof(BLOCK); + if (nBlocksNew == p->data.cblk) + return pv; /* nothing to do! */ + + if (nBlocksNew < p->data.cblk) + { /* shrinking block - chop block in middle and free the upper end */ + pNext = p + nBlocksNew; + pNext->data.cblk = p->data.cblk - nBlocksNew; + p->data.cblk = nBlocksNew; + init_heap_Free(pThis, (PVOID)(pNext + 1)); + return pv; + } + + /* see if next block is free so we can expand in place */ + nBlocksExtra = nBlocksNew - p->data.cblk; + pNext = p + p->data.cblk; + qp = pih->pblkLastAlloc; + for (q = qp->data.pNextFree; ; qp = q, q = q->data.pNextFree) + { + if (q == pNext) + { + if (q->data.cblk < nBlocksExtra) + break; /* cannot get enough blocks by combining next free block */ + qp->data.pNextFree = q->data.pNextFree; /* remove block from free list */ + if (q->data.cblk == nBlocksExtra) + { /* take it all */ + pih->pblkLastAlloc = qp->data.pNextFree; + } + else + { /* chop in two, add first block to existing, free second block */ + pNext += nBlocksExtra; + pNext->data.cblk = q->data.cblk - nBlocksExtra; + init_heap_Free(pThis, (PVOID)(pNext + 1)); + } + p->data.cblk = nBlocksNew; + return pv; + } + if (q == pih->pblkLastAlloc) + break; /* not found */ + } + + /* last ditch effort: allocate new block and copy old contents in */ + pNew = init_heap_Alloc(pThis, cb); + if (!pNew) + return NULL; /* cannot reallocate */ + StrCopyMem(pv, pNew, (p->data.cblk - 1) * sizeof(BLOCK)); + init_heap_Free(pThis, pv); + return pNew; +} + +/* + * Returns the size of a previously-allocated block of memory. + * + * Parameters: + * - pThis = Base interface pointer. + * - pv = Pointer to the block of memory. + * + * Returns: + * The size of the allocated block of memory in bytes, which may be greater than the size requested when + * it was allocated. + */ +SEG_INIT_CODE static SIZE_T init_heap_GetSize(IMalloc *pThis, PVOID pv) +{ + register PBLOCK p; + + if (init_heap_DidAlloc(pThis, pv) != 1) + return (SIZE_T)(-1); /* not our business */ + p = ((PBLOCK)pv) - 1; + return (p->data.cblk - 1) * sizeof(BLOCK); +} + +static const SEG_INIT_RODATA struct IMallocVTable vtblInitHeap = +{ + .QueryInterface = ObjHlpStandardQueryInterface_IMalloc, + .AddRef = ObjHlpStaticAddRefRelease, + .Release = ObjHlpStaticAddRefRelease, + .Alloc = init_heap_Alloc, + .Realloc = init_heap_Realloc, + .Free = init_heap_Free, + .GetSize = init_heap_GetSize, + .DidAlloc = init_heap_DidAlloc, + .HeapMinimize = (void (*)(IMalloc *))ObjHlpDoNothingReturnVoid +}; + +/* + * Returns a reference to the initial heap. + * + * Parameters: + * None. + * + * Returns: + * A reference to the initial heap, in the form of a pointer to its IMalloc interface. + */ +SEG_INIT_CODE IMalloc *_MmGetInitHeap(void) +{ + static SEG_INIT_DATA INITHEAP initheap = { .pblkLastAlloc = NULL }; + register PBLOCK p; + + if (!(initheap.pblkLastAlloc)) + { /* initialize fields of initheap */ + initheap.hdr.pVTable = &vtblInitHeap; + initheap.pblkLastAlloc = initheap.blkBase.data.pNextFree = &(initheap.blkBase); + initheap.blkBase.data.cblk = 0; + /* add g_pInitHeapBlock as the free block in the heap */ + p = (PBLOCK)g_pInitHeapBlock; + p->data.cblk = SIZE_INIT_HEAP / sizeof(BLOCK); + init_heap_Free((IMalloc *)(&initheap), (PVOID)(p + 1)); + } + return (IMalloc *)(&initheap); +} diff --git a/kernel/lib_guids.c b/kernel/lib_guids.c new file mode 100644 index 0000000..a7d5e66 --- /dev/null +++ b/kernel/lib_guids.c @@ -0,0 +1,50 @@ +/* + * 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. + */ +/*------------------------------------------------------------------------------------------------------ + * This module defines all the GUIDs as static data that goes into the library segment (i.e. accessible + * from both supervisor and user modes). The following definitions MUST be first in this source file, + * AND in this order. + *------------------------------------------------------------------------------------------------------ + */ +#include +#define GUIDATTR SEG_LIB_RODATA +#define INITGUID +#include + +/*------------------------------------------------------------------------------------------------- + * Now include all the header files generated from IDL. Try to include them in the order in which + * interfaces are defined. + *------------------------------------------------------------------------------------------------- + */ +#include +#include +#include diff --git a/kernel/memmgr.c b/kernel/memmgr.c new file mode 100644 index 0000000..3ceed8a --- /dev/null +++ b/kernel/memmgr.c @@ -0,0 +1,49 @@ +/* + * 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. + */ +#include +#include +#include +#include + +/*--------------------- + * Initialization code + *--------------------- + */ + +extern void _MmInitVMMap(PSTARTUP_INFO pstartup); +extern void _MmInitPageAlloc(PSTARTUP_INFO pstartup); + +SEG_INIT_CODE void _MmInit(PSTARTUP_INFO pstartup) +{ + _MmInitVMMap(pstartup); + _MmInitPageAlloc(pstartup); +} diff --git a/kernel/objhelp.c b/kernel/objhelp.c new file mode 100644 index 0000000..df82e8e --- /dev/null +++ b/kernel/objhelp.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*-------------------------------------------- + * Standard object functions (API-type calls) + *-------------------------------------------- + */ + +/* + * Determines whether two GUID references are equal. + * + * Parameters: + * - guid1 = First GUID to compare. + * - guid2 = Second GUID to compare. + * + * Returns: + * TRUE if the GUIDs are equal, FALSE otherwise. + */ +SEG_LIB_CODE BOOL IsEqualGUID(REFGUID guid1, REFGUID guid2) +{ + return MAKEBOOL(StrCompareMem(guid1, guid2, sizeof(GUID)) == 0); +} + +/*----------------------------------------------------------------- + * Functions to be used in the construction of C interface vtables + *----------------------------------------------------------------- + */ + +/* + * Retrieves pointers to the supported interfaces on an object. Any pointer returned by this method + * has AddRef called on it before it returns. + * + * Parameters: + * - pThis = Base interface pointer. + * - riid = The identifier of the interface being requested. + * - ppvObject = Address of a pointer variable that receives the interface pointer requested by riid. + * On return, *ppvObject contains the requested interface pointer, or NULL if the interface + * is not supported. + * + * Returns: + * - S_OK = If the interface is supported. *ppvObject contains the pointer to the interface. + * - E_NOINTERFACE = If the interface is not supported. *ppvObject contains NULL. + * - E_POINTER = If ppvObject is NULL. + */ +/* This macro makes a ObjHlpStandardQueryInterface_IXXX function for any interface directly derived from IUnknown */ +#define MAKE_BASE_QI(iface) \ +SEG_LIB_CODE HRESULT ObjHlpStandardQueryInterface_ ## iface (IUnknown *pThis, REFIID riid, PPVOID ppvObject) \ +{ \ + if (!ppvObject) return E_POINTER; \ + *ppvObject = NULL; \ + if (!IsEqualIID(riid, &IID_ ## iface) && !IsEqualIID(riid, &IID_IUnknown)) \ + return E_NOINTERFACE; \ + IUnknown_AddRef(pThis); \ + *ppvObject = (PVOID)pThis; \ + return S_OK; \ +} + +MAKE_BASE_QI(IMalloc) + +/* + * "Dummy" version of AddRef/Release used for static objects. + * + * Parameters: + * - pThis = Base interface pointer. + * + * Returns: + * 1. + */ +SEG_LIB_CODE UINT32 ObjHlpStaticAddRefRelease(IUnknown *pThis) +{ + return 1; +} + +/* + * Method returning void that does nothing. + * + * Parameters: + * - pThis = Base interface pointer. + * + * Returns: + * Nothing. + */ +SEG_LIB_CODE void ObjHlpDoNothingReturnVoid(IUnknown *pThis) +{ + /* do nothing */ +} diff --git a/kernel/pagealloc.c b/kernel/pagealloc.c new file mode 100644 index 0000000..68191f8 --- /dev/null +++ b/kernel/pagealloc.c @@ -0,0 +1,58 @@ +/* + * 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. + */ +#include +#include +#include +#include + +/* Lists we keep track of various pages on. */ +typedef struct tagPAGELIST { + UINT32 ndxLast; /* index of last page in list */ + UINT32 cpg; /* count of pages in list */ +} PAGELIST, *PPAGELIST; + +/* The Master Page Database */ +static PMPDB g_pMasterPageDB = NULL; + +/* Individual page lists. */ +//static PAGELIST g_pglFree = { 0, 0 }; /* pages that are free */ +//static PAGELIST g_pglZeroed = { 0, 0 }; /* pages that are free and zeroed */ +//static PAGELIST g_pglStandby = { 0, 0 }; /* pages removed but "in transition" */ +//static PAGELIST g_pglModified = { 0, 0 }; /* pages removed but "in transition" and modified */ +//static PAGELIST g_pglBad = { 0, 0 }; /* bad pages */ + + + +SEG_INIT_CODE void _MmInitPageAlloc(PSTARTUP_INFO pstartup) +{ + g_pMasterPageDB = (PMPDB)(pstartup->kaMPDB); +} diff --git a/kernel/sizes.h b/kernel/sizes.h new file mode 100644 index 0000000..b32df6e --- /dev/null +++ b/kernel/sizes.h @@ -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. + */ +#ifndef __SIZES_H_INCLUDED +#define __SIZES_H_INCLUDED + +/*----------------------------------- + * Sizes of internal data structures + *----------------------------------- + */ + +#define SIZE_INIT_STACK 4096 /* size of the initial stack */ +#define SIZE_INIT_HEAP 16384 /* size of the initial heap */ + +#endif /* __SIZES_H_INCLUDED */ diff --git a/kernel/start.S b/kernel/start.S index 2210ef5..253439b 100644 --- a/kernel/start.S +++ b/kernel/start.S @@ -31,6 +31,7 @@ */ #include #include +#include "sizes.h" .section ".initHEAD.text" @@ -112,6 +113,10 @@ COMROGUEStart: #endif .section ".init.bss" + .balign 8 +.globl g_pInitHeapBlock +g_pInitHeapBlock: + .space SIZE_INIT_HEAP .balign 4 - .space 4096 + .space SIZE_INIT_STACK .initstack: diff --git a/kernel/strcomparemem.S b/kernel/strcomparemem.S new file mode 100644 index 0000000..4a66508 --- /dev/null +++ b/kernel/strcomparemem.S @@ -0,0 +1,187 @@ +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ +/* + * Copyright (c) 2002 ARM Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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. + */ +/* Taken from FreeBSD memcmp.S, munged by Erbo to COMROGUE standards */ +.section ".lib.text" + +/* Func: INT32 StrCompareMem(PCVOID pMem1, PCVOID pMem2, SSIZE_T cb); */ +/* + * Compares two memory blocks as bytes, returning a value for comparison between the two. + * + * Parameters: + * - pMem1 = First block of memory to compare. + * - pMem2 = Second block of memory to compare. + * - cb = Size of the two memory blocks in bytes. + * + * Returns: + * 0 if the two memory blocks are the same; a value less than 0 if the memory block pointed to by pMem1 is + * less than the one pointed to by pMem2; a value greater than 0 if the memory block pointed to by pMem1 is + * greater than the one pointed to by pMem2. + */ +.globl StrCompareMem +StrCompareMem: + mov ip, r0 + cmp r2, #0x06 /* optimized version for 6-byte compares */ + beq .Lmemcmp_6bytes + mov r0, #0x00 + + /* Are both addresses aligned the same way? */ + cmp r2, #0x00 + eornes r3, ip, r1 + bxeq lr /* len == 0, or same addresses! */ + tst r3, #0x03 + subne r2, r2, #0x01 + bne .Lmemcmp_bytewise2 /* Badly aligned. Do it the slow way */ + + /* Word-align the addresses, if necessary */ + sub r3, r1, #0x05 + ands r3, r3, #0x03 + add r3, r3, r3, lsl #1 + addne pc, pc, r3, lsl #3 + nop + + /* Compare up to 3 bytes */ + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r0, r0, r3 + bxne lr + subs r2, r2, #0x01 + bxeq lr + + /* Compare up to 2 bytes */ + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r0, r0, r3 + bxne lr + subs r2, r2, #0x01 + bxeq lr + + /* Compare 1 byte */ + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r0, r0, r3 + bxne lr + subs r2, r2, #0x01 + bxeq lr + + /* Compare 4 bytes at a time, if possible */ + subs r2, r2, #0x04 + bcc .Lmemcmp_bytewise +.Lmemcmp_word_aligned: + ldr r0, [ip], #0x04 + ldr r3, [r1], #0x04 + subs r2, r2, #0x04 + cmpcs r0, r3 + beq .Lmemcmp_word_aligned + sub r0, r0, r3 + + /* Correct for extra subtraction, and check if done */ + adds r2, r2, #0x04 + cmpeq r0, #0x00 /* If done, did all bytes match? */ + bxeq lr /* Yup. Just return */ + + /* Re-do the final word byte-wise */ + sub ip, ip, #0x04 + sub r1, r1, #0x04 + +.Lmemcmp_bytewise: + add r2, r2, #0x03 +.Lmemcmp_bytewise2: + ldrb r0, [ip], #0x01 + ldrb r3, [r1], #0x01 + subs r2, r2, #0x01 + cmpcs r0, r3 + beq .Lmemcmp_bytewise2 + sub r0, r0, r3 + bx lr + + /* + * 6 byte compares are very common, thanks to the network stack. + * This code is hand-scheduled to reduce the number of stalls for + * load results. Everything else being equal, this will be ~32% + * faster than a byte-wise memcmp. + */ + .align 5 +.Lmemcmp_6bytes: + ldrb r3, [r1, #0x00] /* r3 = b2#0 */ + ldrb r0, [ip, #0x00] /* r0 = b1#0 */ + ldrb r2, [r1, #0x01] /* r2 = b2#1 */ + subs r0, r0, r3 /* r0 = b1#0 - b2#0 */ + ldreqb r3, [ip, #0x01] /* r3 = b1#1 */ + bxne lr /* Return if mismatch on #0 */ + subs r0, r3, r2 /* r0 = b1#1 - b2#1 */ + ldreqb r3, [r1, #0x02] /* r3 = b2#2 */ + ldreqb r0, [ip, #0x02] /* r0 = b1#2 */ + bxne lr /* Return if mismatch on #1 */ + ldrb r2, [r1, #0x03] /* r2 = b2#3 */ + subs r0, r0, r3 /* r0 = b1#2 - b2#2 */ + ldreqb r3, [ip, #0x03] /* r3 = b1#3 */ + bxne lr /* Return if mismatch on #2 */ + subs r0, r3, r2 /* r0 = b1#3 - b2#3 */ + ldreqb r3, [r1, #0x04] /* r3 = b2#4 */ + ldreqb r0, [ip, #0x04] /* r0 = b1#4 */ + bxne lr /* Return if mismatch on #3 */ + ldrb r2, [r1, #0x05] /* r2 = b2#5 */ + subs r0, r0, r3 /* r0 = b1#4 - b2#4 */ + ldreqb r3, [ip, #0x05] /* r3 = b1#5 */ + bxne lr /* Return if mismatch on #4 */ + sub r0, r3, r2 /* r0 = b1#5 - b2#5 */ + bx lr diff --git a/kernel/strcopymem.S b/kernel/strcopymem.S index 1155f10..69db1db 100644 --- a/kernel/strcopymem.S +++ b/kernel/strcopymem.S @@ -58,14 +58,14 @@ * * Apologies for the state of the comments ;-) */ -/* Func: PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, INT32 nBytes); */ +/* Func: PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, SSIZE_T cb); */ /* * Copies memory data from one block of memory to another. Assumes the memory blocks do NOT overlap. * * Parameters: * - pDest = Destination for the copy operation. * - pSrc = Source for the copy operation. - * - nBytes = Number of bytes to be copied. + * - cb = Number of bytes to be copied. * * Returns: * pDest. diff --git a/kernel/strsetmem.S b/kernel/strsetmem.S new file mode 100644 index 0000000..5f66a08 --- /dev/null +++ b/kernel/strsetmem.S @@ -0,0 +1,183 @@ +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ +/* + * Copyright (c) 1995 Mark Brinicombe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ +/* Taken from FreeBSD memset.S, munged by Erbo to COMROGUE standards */ +.section ".lib.text" + +/* FUNC: PVOID StrSetMem(PVOID pMem, INT32 ch, SSIZE_T cb); */ +/* + * Fills a block of memory with a constant byte value. + * + * Parameters: + * - pMem = Pointer to the memory block to be filled. + * - ch = The constant byte (character) to fill that memory with. + * - cb = The size in bytes of the memory block to be filled. + * + * Returns: + * pMem. + */ +.globl StrSetMem +StrSetMem: + and r3, r1, #0xff /* We deal with bytes */ + mov r1, r2 + cmp r1, #0x04 /* Do we have less than 4 bytes */ + mov ip, r0 + blt .Lmemset_lessthanfour + + /* Ok first we will word align the address */ + ands r2, ip, #0x03 /* Get the bottom two bits */ + bne .Lmemset_wordunaligned /* The address is not word aligned */ + + /* We are now word aligned */ +.Lmemset_wordaligned: + orr r3, r3, r3, lsl #8 /* Extend value to 16-bits */ + tst ip, #0x04 /* Quad-align for armv5e */ + orr r3, r3, r3, lsl #16 /* Extend value to 32-bits */ + subne r1, r1, #0x04 /* Quad-align if necessary */ + strne r3, [ip], #0x04 + cmp r1, #0x10 + blt .Lmemset_loop4 /* If less than 16 then use words */ + mov r2, r3 /* Duplicate data */ + cmp r1, #0x80 /* If < 128 then skip the big loop */ + blt .Lmemset_loop32 + + /* Do 128 bytes at a time */ +.Lmemset_loop128: + subs r1, r1, #0x80 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + bgt .Lmemset_loop128 + bxeq lr /* Zero length so just exit */ + + add r1, r1, #0x80 /* Adjust for extra sub */ + + /* Do 32 bytes at a time */ +.Lmemset_loop32: + subs r1, r1, #0x20 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + bgt .Lmemset_loop32 + bxeq lr /* Zero length so just exit */ + + adds r1, r1, #0x10 /* Partially adjust for extra sub */ + + /* Deal with 16 bytes or more */ + strged r2, [ip], #0x08 + strged r2, [ip], #0x08 + bxeq lr /* Zero length so just exit */ + + addlt r1, r1, #0x10 /* Possibly adjust for extra sub */ + + /* We have at least 4 bytes so copy as words */ +.Lmemset_loop4: + subs r1, r1, #0x04 + strge r3, [ip], #0x04 + bgt .Lmemset_loop4 + bxeq lr /* Zero length so just exit */ + + /* Compensate for 64-bit alignment check */ + adds r1, r1, #0x04 + bxeq lr + cmp r1, #2 + + strb r3, [ip], #0x01 /* Set 1 byte */ + strgeb r3, [ip], #0x01 /* Set another byte */ + strgtb r3, [ip] /* and a third */ + bx lr /* Exit */ + +.Lmemset_wordunaligned: + rsb r2, r2, #0x004 + strb r3, [ip], #0x01 /* Set 1 byte */ + cmp r2, #0x02 + strgeb r3, [ip], #0x01 /* Set another byte */ + sub r1, r1, r2 + strgtb r3, [ip], #0x01 /* and a third */ + cmp r1, #0x04 /* More than 4 bytes left? */ + bge .Lmemset_wordaligned /* Yup */ + +.Lmemset_lessthanfour: + cmp r1, #0x00 + bxeq lr /* Zero length so exit */ + strb r3, [ip], #0x01 /* Set 1 byte */ + cmp r1, #0x02 + strgeb r3, [ip], #0x01 /* Set another byte */ + strgtb r3, [ip] /* and a third */ + bx lr /* Exit */ diff --git a/kernel/vmmap.c b/kernel/vmmap.c new file mode 100644 index 0000000..200bde4 --- /dev/null +++ b/kernel/vmmap.c @@ -0,0 +1,465 @@ +/* + * 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. + */ +#include +#include +#include +#include +#include +#include + +#define NMAPFRAMES 4 /* number of frame mappings */ + +static PTTB g_pttb1 = NULL; /* pointer to TTB1 */ +static KERNADDR g_kaEndFence = 0; /* end fence in kernel addresses, after we reserve some */ +static KERNADDR g_kaTableMap[NMAPFRAMES] = { 0 }; /* kernel addresses for page table mappings */ +static PHYSADDR g_paTableMap[NMAPFRAMES] = { 0 }; /* physical addresses for page table mappings */ +static UINT32 g_refTableMap[NMAPFRAMES] = { 0 }; /* reference counts for table mappings */ + +/* + * Maps a page table's page into kernel memory space where we can examine it. + * + * Parameters: + * - paPageTable = Physical address of the page table to map. + * + * Returns: + * Pointer to the pagetable in kernel memory, or NULL if we weren't able to map it. + * + * Side effects: + * May modify g_paTableMap and g_refTableMap, and may modify TTB1 if we map a page into memory. + */ +static PPAGETAB map_pagetable(PHYSADDR paPageTable) +{ + PHYSADDR paOfPage = paPageTable & ~(SYS_PAGE_SIZE - 1); /* actual page table page's PA */ + register UINT32 i; /* loop counter */ + + for (i = 0; i < NMAPFRAMES; i++) + { + if (g_paTableMap[i] == paOfPage) + { + g_refTableMap[i]++; /* already mapped, return it */ + goto returnOK; + } + } + + for (i = 0; i < NMAPFRAMES; i++) + { + if (!(g_paTableMap[i])) + { + g_paTableMap[i] = paOfPage; /* claim slot and map into it */ + g_refTableMap[i] = 1; + if (FAILED(MmMapPages(g_pttb1, g_paTableMap[i], g_kaTableMap[i], 1, TTBFLAGS_KERNEL_DATA, + PGTBLFLAGS_KERNEL_DATA))) + { + g_refTableMap[i] = 0; + g_paTableMap[i] = 0; + return NULL; + } + break; + } + } + if (i == NMAPFRAMES) + return NULL; +returnOK: + return (PPAGETAB)(g_kaTableMap[i] | (paPageTable & (SYS_PAGE_SIZE - 1))); +} + +/* + * Demaps a page table's page from kernel memory space. + * + * Parameters: + * - ppgtbl = Pointer to the page table. + * + * Returns: + * Nothing. + * + * Side effects: + * May modify g_paTableMap and g_refTableMap, and may modify TTB1 if we unmap a page from memory. + */ +static void demap_pagetable(PPAGETAB ppgtbl) +{ + KERNADDR kaOfPage = ((KERNADDR)ppgtbl) & ~(SYS_PAGE_SIZE - 1); + register UINT32 i; /* loop counter */ + + for (i = 0; i < NMAPFRAMES; i++) + { + if (g_kaTableMap[i] == kaOfPage) + { + if (--g_refTableMap[i] == 0) + { + MmDemapPages(g_pttb1, g_kaTableMap[i], 1); + g_paTableMap[i] = 0; + } + break; + } + } +} + +/* + * Resolves a specified TTB to either itself or the global TTB1, depending on whether one was specified + * and on the virtual address to be worked with. + * + * Parameters: + * - pTTB = The specified TTB pointer. + * - vma = The base virtual address we're working with. + * + * Returns: + * The pointer to the selected TTB, which may be the global variable g_pttb1. + */ +static PTTB resolve_ttb(PTTB pTTB, KERNADDR vma) +{ + if (!pTTB || (vma & 0x80000000)) + return g_pttb1; /* if no TTB specified or address is out of range for TTB0, use TTB1 */ + return pTTB; +} + +/* + * Returns the physical address corresponding to a virtual memory address. + * + * Parameters: + * - pTTB = The TTB to resolve the VM address against. If this is NULL or if the address specified + * is outside the TTB0 range, the system TTB is used. + * + * Returns: + * The physical address corresponding to the virtual memory address, or NULL if the address could + * not be resolved (is not mapped, or page table could not be mapped). + */ +PHYSADDR MmGetPhysAddr(PTTB pTTB, KERNADDR vma) +{ + PTTB pTTBEntry = resolve_ttb(pTTB, vma) + mmVMA2TTBIndex(vma); + PPAGETAB pTab; + PHYSADDR rc; + + if ((pTTBEntry->data & TTBQUERY_MASK) == TTBQUERY_FAULT) + return NULL; /* we're not allocated */ + if (pTTBEntry->data & TTBSEC_ALWAYS) + return (pTTBEntry->data & TTBSEC_BASE) | (vma & ~TTBSEC_BASE); /* resolve section address */ + + pTab = map_pagetable(pTTBEntry->data & TTBPGTBL_BASE); + if (!pTab) + return NULL; /* could not map the page table */ + rc = (pTab->pgtbl[mmVMA2PGTBLIndex(vma)].pg.pgaddr << SYS_PAGE_BITS) | (vma & (SYS_PAGE_SIZE - 1)); + demap_pagetable(pTab); + return rc; +} + +/* + * Deallocates page mapping entries within a single current entry in the TTB. + * + * Parameters: + * - pTTBEntry = Pointer to the TTB entry to deallocate in. + * - ndxPage = Starting index in the page table of the first entry to deallocate. + * - cpg = Count of the number of pages to deallocate. Note that this function will not deallocate more + * page mapping entries than remain on the page, as indicated by ndxPage. + * + * Returns: + * Standard HRESULT success/failure. If the result is successful, the SCODE_CODE of the result will + * indicate the number of pages actually deallocated. + * + * Side effects: + * May modify the TTB entry pointed to, and the page table it points to, where applicable. If the + * page table is empty after we finish demapping entries, it may be deallocated. + */ +static HRESULT demap_pages1(PTTB pTTBEntry, UINT32 ndxPage, UINT32 cpg) +{ + UINT32 cpgCurrent; /* number of pages we're mapping */ + PPAGETAB pTab = NULL; /* pointer to current or new page table */ + HRESULT hr; /* return from this function */ + register INT32 i; /* loop counter */ + + /* Figure out how many entries we're going to demap. */ + cpgCurrent = SYS_PGTBL_ENTRIES - ndxPage; /* total free slots on page */ + if (cpg < cpgCurrent) + cpgCurrent = cpg; /* only map up to max requested */ + hr = MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_MEMMGR, cpgCurrent); + + if ((pTTBEntry->data & TTBSEC_ALWAYS) && (cpgCurrent == SYS_PGTBL_ENTRIES) && (ndxPage == 0)) + { /* we can kill off the whole section */ + pTTBEntry->data = 0; + /* TODO: handle TLB and cache */ + } + else if (pTTBEntry->data & TTBPGTBL_ALWAYS) + { + pTab = map_pagetable(pTTBEntry->data & TTBPGTBL_BASE); + if (!pTab) + return MEMMGR_E_NOPGTBL; + for (i = 0; ipgtbl[ndxPage + i].data = 0; + pTab->pgaux[ndxPage + i].data = 0; + /* TODO: handle TLB and cache */ + } + /* TODO: check to see if page table can be deallocated */ + demap_pagetable(pTab); + } + return hr; +} + +HRESULT MmDemapPages(PTTB pTTB, KERNADDR vmaBase, UINT32 cpg) +{ + PTTB pMyTTB = resolve_ttb(pTTB, vmaBase); /* the TTB we use */ + UINT32 ndxTTBMax = (pMyTTB == g_pttb1) ? SYS_TTB1_ENTRIES : SYS_TTB0_ENTRIES; + UINT32 ndxTTB = mmVMA2TTBIndex(vmaBase); /* TTB entry index */ + UINT32 ndxPage = mmVMA2PGTBLIndex(vmaBase); /* starting page entry index */ + UINT32 cpgRemaining = cpg; /* number of pages remaining to demap */ + HRESULT hr; /* temporary result */ + + if ((cpgRemaining > 0) && (ndxPage > 0)) + { + /* We are starting in the middle of a VM page. Demap to the end of the VM page. */ + hr = demap_pages1(pMyTTB + ndxTTB, ndxPage, cpgRemaining); + if (FAILED(hr)) + return hr; + cpgRemaining -= SCODE_CODE(hr); + if (++ndxTTB == ndxTTBMax) + return MEMMGR_E_ENDTTB; + } + + while (cpgRemaining > 0) + { + hr = demap_pages1(pMyTTB + ndxTTB, 0, cpgRemaining); + if (FAILED(hr)) + return hr; + cpgRemaining -= SCODE_CODE(hr); + if (++ndxTTB == ndxTTBMax) + return MEMMGR_E_ENDTTB; + } + return S_OK; +} + +/* + * 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; +} + +static HRESULT map_pages1(PTTB pttbEntry, PHYSADDR paBase, UINT32 ndxPage, UINT32 cpg, UINT32 uiTableFlags, + UINT32 uiPageFlags) +{ + UINT32 cpgCurrent; /* number of pages we're mapping */ + PPAGETAB pTab = NULL; /* pointer to current or new page table */ + HRESULT hr; /* return from this function */ + register INT32 i; /* loop counter */ + + switch (pttbEntry->data & TTBQUERY_MASK) + { + case TTBQUERY_FAULT: /* not allocated, allocate a new page table for the slot */ + /* TODO: allocate something into pTab */ + if (!pTab) + return MEMMGR_E_NOPGTBL; + for (i=0; ipgtbl[i].data = 0; /* blank out the new page table */ + pTab->pgaux[i].data = 0; + } + /* TODO: use physical address of page here */ + pttbEntry->data = MmGetPhysAddr(g_pttb1, (KERNADDR)pTab) | uiTableFlags; /* poke new entry */ + break; + + case TTBQUERY_PGTBL: /* existing page table */ + if ((pttbEntry->data & TTBPGTBL_ALLFLAGS) != uiTableFlags) + return MEMMGR_E_BADTTBFLG; /* table flags not compatible */ + pTab = map_pagetable(pttbEntry->data & TTBPGTBL_BASE); + if (!pTab) + return MEMMGR_E_NOPGTBL; /* could not map the page table */ + break; + + case TTBQUERY_SEC: + case TTBQUERY_PXNSEC: + /* this is a section, make sure its base address covers this mapping and its flags are compatible */ + if ((pttbEntry->data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags)) + return MEMMGR_E_BADTTBFLG; + if ((pttbEntry->data & TTBSEC_BASE) != (paBase & TTBSEC_BASE)) + return MEMMGR_E_COLLIDED; + 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 */ + hr = MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_MEMMGR, cpgCurrent); + + if (!(pttbEntry->data & TTBSEC_ALWAYS)) + { + /* fill in entries in the page table */ + for (i=0; i < cpgCurrent; i++) + { + if ((pTab->pgtbl[ndxPage + i].data & PGQUERY_MASK) != PGQUERY_FAULT) + { + while (--i >= 0) + { /* reverse any mapping we've done in this function */ + pTab->pgtbl[ndxPage + i].data = 0; + pTab->pgaux[ndxPage + i].data = 0; + } + hr = MEMMGR_E_COLLIDED; /* stepping on existing mapping */ + goto exit; + } + pTab->pgtbl[ndxPage + i].data = paBase | uiPageFlags; + pTab->pgaux[ndxPage + i].data = 0; /* TODO */ + paBase += SYS_PAGE_SIZE; + } + } +exit: + demap_pagetable(pTab); + return hr; +} + +HRESULT MmMapPages(PTTB pTTB, PHYSADDR paBase, KERNADDR vmaBase, UINT32 cpg, UINT32 uiTableFlags, + UINT32 uiPageFlags) +{ + PTTB pMyTTB = resolve_ttb(pTTB, vmaBase); /* the TTB we use */ + UINT32 ndxTTBMax = (pMyTTB == g_pttb1) ? SYS_TTB1_ENTRIES : SYS_TTB0_ENTRIES; + UINT32 ndxTTB = mmVMA2TTBIndex(vmaBase); /* TTB entry index */ + UINT32 ndxPage = mmVMA2PGTBLIndex(vmaBase); /* starting page entry index */ + UINT32 cpgRemaining = cpg; /* number of pages remaining to map */ + HRESULT hr; /* temporary result */ + + if ((cpgRemaining > 0) && (ndxPage > 0)) + { + /* We are starting in the middle of a VM page. Map to the end of the VM page. */ + hr = map_pages1(pMyTTB + ndxTTB, paBase, ndxPage, cpgRemaining, uiTableFlags, uiPageFlags); + if (FAILED(hr)) + return hr; + cpgRemaining -= SCODE_CODE(hr); + paBase += (SCODE_CODE(hr) << SYS_PAGE_BITS); + if (++ndxTTB == ndxTTBMax) + { + hr = MEMMGR_E_ENDTTB; + goto errorExit; + } + } + + while (cpgRemaining >= 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 (pMyTTB[ndxTTB].data & TTBQUERY_MASK) + { + case TTBQUERY_FAULT: /* unmapped - map the section */ + pMyTTB[ndxTTB].data = paBase | make_section_flags(uiTableFlags, uiPageFlags); + break; + + case TTBQUERY_PGTBL: /* collided with a page table */ + hr = MEMMGR_E_COLLIDED; + goto errorExit; + + case TTBQUERY_SEC: /* test existing section */ + case TTBQUERY_PXNSEC: + if ((pMyTTB[ndxTTB].data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags)) + { + hr = MEMMGR_E_BADTTBFLG; + goto errorExit; + } + if ((pMyTTB[ndxTTB].data & TTBSEC_BASE) != paBase) + { + hr = MEMMGR_E_COLLIDED; + goto errorExit; + } + break; + } + /* we mapped a whole section worth */ + hr = MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_MEMMGR, SYS_PGTBL_ENTRIES); + } + else + { + /* just map 256 individual pages */ + hr = map_pages1(pMyTTB + ndxTTB, paBase, 0, cpgRemaining, uiTableFlags, uiPageFlags); + if (FAILED(hr)) + goto errorExit; + } + /* adjust base physical address, page count, and TTB index */ + paBase += (SCODE_CODE(hr) << SYS_PAGE_BITS); + cpgRemaining -= SCODE_CODE(hr); + if (++ndxTTB == ndxTTBMax) + { + hr = MEMMGR_E_ENDTTB; + goto errorExit; + } + } + + if (cpgRemaining > 0) + { + /* map the "tail end" onto the next TTB */ + hr = map_pages1(pMyTTB + ndxTTB, paBase, 0, cpgRemaining, uiTableFlags, uiPageFlags); + if (FAILED(hr)) + goto errorExit; + } + return S_OK; +errorExit: + /* demap everything we've managed to map thusfar */ + MmDemapPages(pMyTTB, vmaBase, cpg - cpgRemaining); + return hr; +} + +/*--------------------- + * Initialization code + *--------------------- + */ + +SEG_INIT_CODE void _MmInitVMMap(PSTARTUP_INFO pstartup) +{ + UINT32 i; /* loop counter */ + + g_pttb1 = (PTTB)(pstartup->kaTTB); + g_kaEndFence = pstartup->vmaFirstFree; + for (i=0; i