Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:41

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreMemory
0007  *
0008  * @brief This source file contains the i386/pc386 implementation of
0009  *   _Memory_Get().
0010  */
0011 
0012 /*
0013  * Copyright (C) 2019 embedded brains GmbH & Co. KG
0014  *
0015  * Copyright (C) 1989, 2017 On-Line Applications Research Corporation (OAR)
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 /* #define BSP_GET_WORK_AREA_DEBUG */
0040 #include <bsp.h>
0041 #include <bsp/bootcard.h>
0042 
0043 #include <rtems/sysinit.h>
0044 
0045 #ifdef BSP_GET_WORK_AREA_DEBUG
0046   #include <rtems/bspIo.h>
0047 #endif
0048 
0049 /*
0050  *  These are provided by the linkcmds.
0051  */
0052 extern char   WorkAreaBase[];
0053 extern char   HeapSize[];
0054 extern char   RamSize[];
0055 
0056 /* rudimentary multiboot info */
0057 struct multiboot_info {
0058   uint32_t  flags;       /* start.S only raises flags for items actually */
0059                          /* saved; this allows us to check for the size  */
0060                          /* of the data structure.                       */
0061   uint32_t  mem_lower;  /* avail kB in lower memory */
0062   uint32_t  mem_upper;  /* avail kB in lower memory */
0063   /* ... (unimplemented) */
0064 };
0065 
0066 extern struct multiboot_info _boot_multiboot_info;
0067 
0068 /*
0069  *  This is the first address of the memory we can use for the RTEMS
0070  *  Work Area.
0071  */ 
0072 static uintptr_t rtemsWorkAreaStart;
0073 
0074 /*
0075  * Board's memory size easily be overridden by application.
0076  */
0077 uint32_t bsp_mem_size = 0;
0078 
0079 static void bsp_size_memory(void)
0080 {
0081   uintptr_t topAddr;
0082 
0083   /* Set the value of start of free memory. */
0084   rtemsWorkAreaStart = (uint32_t)WorkAreaBase;
0085 
0086   /* Align the RTEMS Work Area at beginning of free memory. */
0087   if (rtemsWorkAreaStart & (CPU_ALIGNMENT - 1))  /* not aligned => align it */
0088     rtemsWorkAreaStart = (rtemsWorkAreaStart+CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1);
0089 
0090   /* The memory detection algorithm is very crude; try
0091    * to use multiboot info, if possible (set from start.S)
0092    */
0093   if ( ((uintptr_t)RamSize == (uintptr_t) 0xFFFFFFFF)  &&
0094        (_boot_multiboot_info.flags & 1) &&
0095        _boot_multiboot_info.mem_upper ) {
0096     topAddr = _boot_multiboot_info.mem_upper * 1024;
0097     #ifdef BSP_GET_WORK_AREA_DEBUG
0098       printk( "Multiboot info says we have 0x%08x\n", topAddr );
0099     #endif
0100   } else if ( (uintptr_t) RamSize == (uintptr_t) 0xFFFFFFFF ) {
0101     uintptr_t lowest;
0102     uint32_t  val;
0103     int       i;
0104 
0105     /*
0106      * We have to dynamically size memory. Memory size can be anything
0107      * between no less than 2M and 2048M.  If we can write a value to
0108      * an address and read the same value back, then the memory is there.
0109      *
0110      * WARNING: This can detect memory which should be reserved for
0111      *          graphics controllers which share the CPU's RAM.
0112      */
0113 
0114     /* find the lowest 1M boundary to probe */
0115     lowest = ((rtemsWorkAreaStart + (1<<20)) >> 20) + 1;
0116     if ( lowest  < 2 )
0117       lowest = 2;
0118 
0119     for (i=2048; i>=lowest; i--) {
0120       topAddr = i*1024*1024 - 4;
0121       *(volatile uint32_t*)topAddr = topAddr;
0122     }
0123 
0124     for(i=lowest; i<=2048; i++) {
0125       topAddr = i*1024*1024 - 4;
0126       val =  *(volatile uint32_t*)topAddr;
0127       if (val != topAddr) {
0128         break;
0129       }
0130     }
0131 
0132     topAddr = (i-1)*1024*1024;
0133     #ifdef BSP_GET_WORK_AREA_DEBUG
0134       printk( "Dynamically sized to 0x%08x\n", topAddr );
0135     #endif
0136   } else {
0137     topAddr = (uintptr_t) RamSize;
0138     #ifdef BSP_GET_WORK_AREA_DEBUG
0139       printk( "hardcoded to 0x%08x\n", topAddr );
0140     #endif
0141   }
0142 
0143   bsp_mem_size = topAddr;
0144 }
0145 
0146 static Memory_Area _Memory_Areas[ 1 ];
0147 
0148 static void bsp_memory_initialize( void )
0149 {
0150   /*
0151    *  We need to determine how much memory there is in the system.
0152    */
0153   bsp_size_memory();
0154 
0155   _Memory_Initialize_by_size(
0156     &_Memory_Areas[0],
0157     (void *) rtemsWorkAreaStart,
0158     (uintptr_t) bsp_mem_size - (uintptr_t) rtemsWorkAreaStart
0159   );
0160 }
0161 
0162 RTEMS_SYSINIT_ITEM(
0163   bsp_memory_initialize,
0164   RTEMS_SYSINIT_MEMORY,
0165   RTEMS_SYSINIT_ORDER_MIDDLE
0166 );
0167 
0168 static const Memory_Information _Memory_Information =
0169   MEMORY_INFORMATION_INITIALIZER( _Memory_Areas );
0170 
0171 const Memory_Information *_Memory_Get( void )
0172 {
0173   return &_Memory_Information;
0174 }