Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpcmem.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00017 * 00018 * Note: Most of this code comes from the old file "i386mem.c", which 00019 * was Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com> 00020 */ 00021 00022 #include <freeldr.h> 00023 #include <arch/pc/x86common.h> 00024 00025 #define NDEBUG 00026 #include <debug.h> 00027 00028 DBG_DEFAULT_CHANNEL(MEMORY); 00029 00030 #define MAX_BIOS_DESCRIPTORS 32 00031 #define FREELDR_BASE_PAGE (FREELDR_BASE / PAGE_SIZE) 00032 #define FILEBUF_BASE_PAGE (FILESYSBUFFER / PAGE_SIZE) 00033 #define DISKBUF_BASE_PAGE (DISKREADBUFFER / PAGE_SIZE) 00034 #define STACK_BASE_PAGE (DISKBUF_BASE_PAGE + 1) 00035 #define STACK_END_PAGE (STACK32ADDR / PAGE_SIZE) 00036 #define BIOSBUF_BASE_PAGE (BIOSCALLBUFFER / PAGE_SIZE) 00037 00038 #define FREELDR_PAGE_COUNT (FILEBUF_BASE_PAGE - FREELDR_BASE_PAGE) 00039 #define FILEBUF_PAGE_COUNT (DISKBUF_BASE_PAGE - FILEBUF_BASE_PAGE) 00040 #define DISKBUF_PAGE_COUNT (1) 00041 #define STACK_PAGE_COUNT (STACK_END_PAGE - STACK_BASE_PAGE) 00042 #define BIOSBUF_PAGE_COUNT (1) 00043 00044 BIOS_MEMORY_MAP PcBiosMemoryMap[MAX_BIOS_DESCRIPTORS]; 00045 ULONG PcBiosMapCount; 00046 00047 FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS + 1] = 00048 { 00049 { LoaderFirmwarePermanent, 0x00, 1 }, // realmode int vectors 00050 { LoaderFirmwareTemporary, 0x01, FREELDR_BASE_PAGE - 1 }, // freeldr stack + cmdline 00051 { LoaderLoadedProgram, FREELDR_BASE_PAGE, FREELDR_PAGE_COUNT }, // freeldr image 00052 { LoaderFirmwareTemporary, FILEBUF_BASE_PAGE, FILEBUF_PAGE_COUNT }, // File system read buffer. FILESYSBUFFER 00053 { LoaderFirmwareTemporary, DISKBUF_BASE_PAGE, DISKBUF_PAGE_COUNT }, // Disk read buffer for int 13h. DISKREADBUFFER 00054 { LoaderOsloaderStack, STACK_BASE_PAGE, STACK_PAGE_COUNT }, // prot mode stack. 00055 { LoaderFirmwareTemporary, BIOSBUF_BASE_PAGE, BIOSBUF_PAGE_COUNT }, // BIOSCALLBUFFER 00056 { LoaderFirmwarePermanent, 0xA0, 0x50 }, // ROM / Video 00057 { LoaderSpecialMemory, 0xF0, 0x10 }, // ROM / Video 00058 { LoaderSpecialMemory, 0xFFF, 1 }, // unusable memory 00059 { 0, 0, 0 }, // end of map 00060 }; 00061 00062 ULONG 00063 AddMemoryDescriptor( 00064 IN OUT PFREELDR_MEMORY_DESCRIPTOR List, 00065 IN ULONG MaxCount, 00066 IN PFN_NUMBER BasePage, 00067 IN PFN_NUMBER PageCount, 00068 IN TYPE_OF_MEMORY MemoryType); 00069 00070 static 00071 BOOLEAN 00072 GetExtendedMemoryConfiguration(ULONG* pMemoryAtOneMB /* in KB */, ULONG* pMemoryAtSixteenMB /* in 64KB */) 00073 { 00074 REGS RegsIn; 00075 REGS RegsOut; 00076 00077 TRACE("GetExtendedMemoryConfiguration()\n"); 00078 00079 *pMemoryAtOneMB = 0; 00080 *pMemoryAtSixteenMB = 0; 00081 00082 // Int 15h AX=E801h 00083 // Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS 00084 // 00085 // AX = E801h 00086 // Return: 00087 // CF clear if successful 00088 // AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB) 00089 // BX = extended memory above 16M, in 64K blocks 00090 // CX = configured memory 1M to 16M, in K 00091 // DX = configured memory above 16M, in 64K blocks 00092 // CF set on error 00093 RegsIn.w.ax = 0xE801; 00094 Int386(0x15, &RegsIn, &RegsOut); 00095 00096 TRACE("Int15h AX=E801h\n"); 00097 TRACE("AX = 0x%x\n", RegsOut.w.ax); 00098 TRACE("BX = 0x%x\n", RegsOut.w.bx); 00099 TRACE("CX = 0x%x\n", RegsOut.w.cx); 00100 TRACE("DX = 0x%x\n", RegsOut.w.dx); 00101 TRACE("CF set = %s\n\n", (RegsOut.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE"); 00102 00103 if (INT386_SUCCESS(RegsOut)) 00104 { 00105 // If AX=BX=0000h the use CX and DX 00106 if (RegsOut.w.ax == 0) 00107 { 00108 // Return extended memory size in K 00109 *pMemoryAtSixteenMB = RegsOut.w.dx; 00110 *pMemoryAtOneMB = RegsOut.w.cx; 00111 return TRUE; 00112 } 00113 else 00114 { 00115 // Return extended memory size in K 00116 *pMemoryAtSixteenMB = RegsOut.w.bx; 00117 *pMemoryAtOneMB = RegsOut.w.ax; 00118 return TRUE; 00119 } 00120 } 00121 00122 // If we get here then Int15 Func E801h didn't work 00123 // So try Int15 Func 88h 00124 // Int 15h AH=88h 00125 // SYSTEM - GET EXTENDED MEMORY SIZE (286+) 00126 // 00127 // AH = 88h 00128 // Return: 00129 // CF clear if successful 00130 // AX = number of contiguous KB starting at absolute address 100000h 00131 // CF set on error 00132 // AH = status 00133 // 80h invalid command (PC,PCjr) 00134 // 86h unsupported function (XT,PS30) 00135 RegsIn.b.ah = 0x88; 00136 Int386(0x15, &RegsIn, &RegsOut); 00137 00138 TRACE("Int15h AH=88h\n"); 00139 TRACE("AX = 0x%x\n", RegsOut.w.ax); 00140 TRACE("CF set = %s\n\n", (RegsOut.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE"); 00141 00142 if (INT386_SUCCESS(RegsOut) && RegsOut.w.ax != 0) 00143 { 00144 *pMemoryAtOneMB = RegsOut.w.ax; 00145 return TRUE; 00146 } 00147 00148 // If we get here then Int15 Func 88h didn't work 00149 // So try reading the CMOS 00150 WRITE_PORT_UCHAR((PUCHAR)0x70, 0x31); 00151 *pMemoryAtOneMB = READ_PORT_UCHAR((PUCHAR)0x71); 00152 *pMemoryAtOneMB = (*pMemoryAtOneMB & 0xFFFF); 00153 *pMemoryAtOneMB = (*pMemoryAtOneMB << 8); 00154 00155 TRACE("Int15h Failed\n"); 00156 TRACE("CMOS reports: 0x%x\n", *pMemoryAtOneMB); 00157 00158 if (*pMemoryAtOneMB != 0) 00159 { 00160 return TRUE; 00161 } 00162 00163 return FALSE; 00164 } 00165 00166 static ULONG 00167 PcMemGetConventionalMemorySize(VOID) 00168 { 00169 REGS Regs; 00170 00171 TRACE("GetConventionalMemorySize()\n"); 00172 00173 /* Int 12h 00174 * BIOS - GET MEMORY SIZE 00175 * 00176 * Return: 00177 * AX = kilobytes of contiguous memory starting at absolute address 00000h 00178 * 00179 * This call returns the contents of the word at 0040h:0013h; 00180 * in PC and XT, this value is set from the switches on the motherboard 00181 */ 00182 Regs.w.ax = 0; 00183 Int386(0x12, &Regs, &Regs); 00184 00185 TRACE("Int12h\n"); 00186 TRACE("AX = 0x%x\n\n", Regs.w.ax); 00187 00188 return (ULONG)Regs.w.ax; 00189 } 00190 00191 static 00192 ULONG 00193 PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize) 00194 { 00195 REGS Regs; 00196 ULONG MapCount = 0; 00197 ULONGLONG RealBaseAddress, RealSize; 00198 TYPE_OF_MEMORY MemoryType; 00199 ASSERT(PcBiosMapCount == 0); 00200 00201 TRACE("GetBiosMemoryMap()\n"); 00202 00203 /* Int 15h AX=E820h 00204 * Newer BIOSes - GET SYSTEM MEMORY MAP 00205 * 00206 * AX = E820h 00207 * EAX = 0000E820h 00208 * EDX = 534D4150h ('SMAP') 00209 * EBX = continuation value or 00000000h to start at beginning of map 00210 * ECX = size of buffer for result, in bytes (should be >= 20 bytes) 00211 * ES:DI -> buffer for result 00212 * Return: 00213 * CF clear if successful 00214 * EAX = 534D4150h ('SMAP') 00215 * ES:DI buffer filled 00216 * EBX = next offset from which to copy or 00000000h if all done 00217 * ECX = actual length returned in bytes 00218 * CF set on error 00219 * AH = error code (86h) 00220 */ 00221 Regs.x.ebx = 0x00000000; 00222 00223 while (PcBiosMapCount < MAX_BIOS_DESCRIPTORS) 00224 { 00225 /* Setup the registers for the BIOS call */ 00226 Regs.x.eax = 0x0000E820; 00227 Regs.x.edx = 0x534D4150; /* ('SMAP') */ 00228 /* Regs.x.ebx = 0x00000001; Continuation value already set */ 00229 Regs.x.ecx = sizeof(BIOS_MEMORY_MAP); 00230 Regs.w.es = BIOSCALLBUFSEGMENT; 00231 Regs.w.di = BIOSCALLBUFOFFSET; 00232 Int386(0x15, &Regs, &Regs); 00233 00234 TRACE("Memory Map Entry %d\n", PcBiosMapCount); 00235 TRACE("Int15h AX=E820h\n"); 00236 TRACE("EAX = 0x%x\n", Regs.x.eax); 00237 TRACE("EBX = 0x%x\n", Regs.x.ebx); 00238 TRACE("ECX = 0x%x\n", Regs.x.ecx); 00239 TRACE("CF set = %s\n", (Regs.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE"); 00240 00241 /* If the BIOS didn't return 'SMAP' in EAX then 00242 * it doesn't support this call. If CF is set, we're done */ 00243 if (Regs.x.eax != 0x534D4150 || !INT386_SUCCESS(Regs)) 00244 { 00245 break; 00246 } 00247 00248 /* Copy data to global buffer */ 00249 RtlCopyMemory(&PcBiosMemoryMap[PcBiosMapCount], (PVOID)BIOSCALLBUFFER, Regs.x.ecx); 00250 00251 TRACE("BaseAddress: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].BaseAddress); 00252 TRACE("Length: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].Length); 00253 TRACE("Type: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Type); 00254 TRACE("Reserved: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Reserved); 00255 TRACE("\n"); 00256 00257 /* Check if this is free memory */ 00258 if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryUsable) 00259 { 00260 MemoryType = LoaderFree; 00261 00262 /* Align up base of memory area */ 00263 RealBaseAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress & ~(MM_PAGE_SIZE - 1ULL); 00264 00265 /* Calculate the length after aligning the base */ 00266 RealSize = PcBiosMemoryMap[PcBiosMapCount].BaseAddress + 00267 PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress; 00268 RealSize = (RealSize + MM_PAGE_SIZE - 1) & ~(MM_PAGE_SIZE - 1ULL); 00269 } 00270 else 00271 { 00272 if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryReserved) 00273 MemoryType = LoaderFirmwarePermanent; 00274 else 00275 MemoryType = LoaderSpecialMemory; 00276 00277 /* Align down base of memory area */ 00278 RealBaseAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress & ~(MM_PAGE_SIZE - 1ULL); 00279 /* Calculate the length after aligning the base */ 00280 RealSize = PcBiosMemoryMap[PcBiosMapCount].BaseAddress + 00281 PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress; 00282 RealSize = (RealSize + MM_PAGE_SIZE - 1) & ~(MM_PAGE_SIZE - 1ULL); 00283 } 00284 00285 /* Check if we can add this descriptor */ 00286 if ((RealSize >= MM_PAGE_SIZE) && (MapCount < MaxMemoryMapSize)) 00287 { 00288 /* Add the descriptor */ 00289 MapCount = AddMemoryDescriptor(PcMemoryMap, 00290 MAX_BIOS_DESCRIPTORS, 00291 RealBaseAddress / MM_PAGE_SIZE, 00292 RealSize / MM_PAGE_SIZE, 00293 MemoryType); 00294 } 00295 00296 PcBiosMapCount++; 00297 00298 /* If the continuation value is zero or the 00299 * carry flag is set then this was 00300 * the last entry so we're done */ 00301 if (Regs.x.ebx == 0x00000000) 00302 { 00303 TRACE("End Of System Memory Map!\n\n"); 00304 break; 00305 } 00306 00307 } 00308 00309 return MapCount; 00310 } 00311 00312 00313 PFREELDR_MEMORY_DESCRIPTOR 00314 PcMemGetMemoryMap(ULONG *MemoryMapSize) 00315 { 00316 ULONG i, EntryCount; 00317 ULONG ExtendedMemorySizeAtOneMB; 00318 ULONG ExtendedMemorySizeAtSixteenMB; 00319 00320 EntryCount = PcMemGetBiosMemoryMap(PcMemoryMap, MAX_BIOS_DESCRIPTORS); 00321 00322 /* If the BIOS didn't provide a memory map, synthesize one */ 00323 if (0 == EntryCount) 00324 { 00325 GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB, &ExtendedMemorySizeAtSixteenMB); 00326 00327 /* Conventional memory */ 00328 AddMemoryDescriptor(PcMemoryMap, 00329 MAX_BIOS_DESCRIPTORS, 00330 0, 00331 PcMemGetConventionalMemorySize() * 1024 / PAGE_SIZE, 00332 LoaderFree); 00333 00334 /* Extended memory */ 00335 EntryCount = AddMemoryDescriptor(PcMemoryMap, 00336 MAX_BIOS_DESCRIPTORS, 00337 1024 * 1024 / PAGE_SIZE, 00338 ExtendedMemorySizeAtOneMB * 1024 / PAGE_SIZE, 00339 LoaderFree); 00340 00341 if (ExtendedMemorySizeAtSixteenMB != 0) 00342 { 00343 /* Extended memory at 16MB */ 00344 EntryCount = AddMemoryDescriptor(PcMemoryMap, 00345 MAX_BIOS_DESCRIPTORS, 00346 0x1000000 / PAGE_SIZE, 00347 ExtendedMemorySizeAtSixteenMB * 64 * 1024 / PAGE_SIZE, 00348 LoaderFree); 00349 } 00350 } 00351 00352 TRACE("Dumping resulting memory map:\n"); 00353 for (i = 0; i < EntryCount; i++) 00354 { 00355 TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n", 00356 PcMemoryMap[i].BasePage, 00357 PcMemoryMap[i].PageCount, 00358 MmGetSystemMemoryMapTypeString(PcMemoryMap[i].MemoryType)); 00359 } 00360 00361 *MemoryMapSize = EntryCount; 00362 00363 return PcMemoryMap; 00364 } 00365 00366 /* EOF */ Generated on Sat May 26 2012 04:17:53 for ReactOS by
1.7.6.1
|