1 /* 2 * FreeLoader 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Note: much of this code was based on knowledge and/or code developed 19 * by the Xbox Linux group: http://www.xbox-linux.org 20 */ 21 22 #include <freeldr.h> 23 #include <debug.h> 24 25 DBG_DEFAULT_CHANNEL(MEMORY); 26 27 static ULONG InstalledMemoryMb = 0; 28 static ULONG AvailableMemoryMb = 0; 29 extern multiboot_info_t * MultibootInfoPtr; 30 extern PVOID FrameBuffer; 31 extern ULONG FrameBufferSize; 32 33 #define TEST_SIZE 0x200 34 #define TEST_PATTERN1 0xAA 35 #define TEST_PATTERN2 0x55 36 37 extern VOID 38 SetMemory( 39 PFREELDR_MEMORY_DESCRIPTOR MemoryMap, 40 ULONG_PTR BaseAddress, 41 SIZE_T Size, 42 TYPE_OF_MEMORY MemoryType); 43 44 extern VOID 45 ReserveMemory( 46 PFREELDR_MEMORY_DESCRIPTOR MemoryMap, 47 ULONG_PTR BaseAddress, 48 SIZE_T Size, 49 TYPE_OF_MEMORY MemoryType, 50 PCHAR Usage); 51 52 extern ULONG 53 PcMemFinalizeMemoryMap( 54 PFREELDR_MEMORY_DESCRIPTOR MemoryMap); 55 56 VOID 57 XboxMemInit(VOID) 58 { 59 UCHAR ControlRegion[TEST_SIZE]; 60 PVOID MembaseTop = (PVOID)(64 * 1024 * 1024); 61 PVOID MembaseLow = (PVOID)0; 62 63 (*(PULONG)(0xfd000000 + 0x100200)) = 0x03070103; 64 (*(PULONG)(0xfd000000 + 0x100204)) = 0x11448000; 65 66 WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); 67 WRITE_PORT_ULONG((ULONG*) 0xcfc, 0x7ffffff); /* Prep hardware for 128 Mb */ 68 69 InstalledMemoryMb = 64; 70 memset(ControlRegion, TEST_PATTERN1, TEST_SIZE); 71 memset(MembaseTop, TEST_PATTERN1, TEST_SIZE); 72 __wbinvd(); 73 74 if (memcmp(MembaseTop, ControlRegion, TEST_SIZE) == 0) 75 { 76 /* Looks like there is memory .. maybe a 128MB box */ 77 memset(ControlRegion, TEST_PATTERN2, TEST_SIZE); 78 memset(MembaseTop, TEST_PATTERN2, TEST_SIZE); 79 __wbinvd(); 80 if (memcmp(MembaseTop, ControlRegion, TEST_SIZE) == 0) 81 { 82 /* Definitely looks like there is memory */ 83 if (memcmp(MembaseLow, ControlRegion, TEST_SIZE) == 0) 84 { 85 /* Hell, we find the Test-string at 0x0 too! */ 86 InstalledMemoryMb = 64; 87 } 88 else 89 { 90 InstalledMemoryMb = 128; 91 } 92 } 93 } 94 95 /* Set hardware for amount of memory detected */ 96 WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); 97 WRITE_PORT_ULONG((ULONG*) 0xcfc, InstalledMemoryMb * 1024 * 1024 - 1); 98 99 AvailableMemoryMb = InstalledMemoryMb; 100 } 101 102 memory_map_t * 103 XboxGetMultibootMemoryMap(INT * Count) 104 { 105 memory_map_t * MemoryMap; 106 107 if (!MultibootInfoPtr) 108 { 109 ERR("Multiboot info structure not found!\n"); 110 return NULL; 111 } 112 113 if (!(MultibootInfoPtr->flags & MB_INFO_FLAG_MEMORY_MAP)) 114 { 115 ERR("Multiboot memory map is not passed!\n"); 116 return NULL; 117 } 118 119 MemoryMap = (memory_map_t *)MultibootInfoPtr->mmap_addr; 120 121 if (!MemoryMap || 122 MultibootInfoPtr->mmap_length == 0 || 123 MultibootInfoPtr->mmap_length % sizeof(memory_map_t) != 0) 124 { 125 ERR("Multiboot memory map structure is malformed!\n"); 126 return NULL; 127 } 128 129 *Count = MultibootInfoPtr->mmap_length / sizeof(memory_map_t); 130 return MemoryMap; 131 } 132 133 TYPE_OF_MEMORY 134 XboxMultibootMemoryType(ULONG Type) 135 { 136 switch (Type) 137 { 138 case 0: // Video RAM 139 return LoaderFirmwarePermanent; 140 case 1: // Available RAM 141 return LoaderFree; 142 case 3: // ACPI area 143 return LoaderFirmwareTemporary; 144 case 4: // Hibernation area 145 return LoaderSpecialMemory; 146 case 5: // Reserved or invalid memory 147 return LoaderSpecialMemory; 148 default: 149 return LoaderFirmwarePermanent; 150 } 151 } 152 153 FREELDR_MEMORY_DESCRIPTOR XboxMemoryMap[MAX_BIOS_DESCRIPTORS + 1]; 154 155 PFREELDR_MEMORY_DESCRIPTOR 156 XboxMemGetMemoryMap(ULONG *MemoryMapSize) 157 { 158 memory_map_t * MbMap; 159 INT Count, i; 160 161 TRACE("XboxMemGetMemoryMap()\n"); 162 163 MbMap = XboxGetMultibootMemoryMap(&Count); 164 if (MbMap) 165 { 166 /* Obtain memory map via multiboot spec */ 167 168 for (i = 0; i < Count; i++, MbMap++) 169 { 170 TRACE("i = %d, base_addr_low = 0x%p, length_low = 0x%p\n", i, MbMap->base_addr_low, MbMap->length_low); 171 172 if (MbMap->base_addr_high > 0 || MbMap->length_high > 0) 173 { 174 ERR("Memory descriptor base or size is greater than 4 GB, should not happen on Xbox!\n"); 175 ASSERT(FALSE); 176 } 177 178 SetMemory(XboxMemoryMap, 179 MbMap->base_addr_low, 180 MbMap->length_low, 181 XboxMultibootMemoryType(MbMap->type)); 182 } 183 } 184 else 185 { 186 /* Synthesize memory map */ 187 188 /* Available RAM block */ 189 SetMemory(XboxMemoryMap, 190 0, 191 AvailableMemoryMb * 1024 * 1024, 192 LoaderFree); 193 194 if (FrameBufferSize != 0) 195 { 196 /* Video memory */ 197 ReserveMemory(XboxMemoryMap, 198 (ULONG_PTR)FrameBuffer, 199 FrameBufferSize, 200 LoaderFirmwarePermanent, 201 "Video memory"); 202 } 203 } 204 205 *MemoryMapSize = PcMemFinalizeMemoryMap(XboxMemoryMap); 206 return XboxMemoryMap; 207 } 208 209 /* EOF */ 210