4 * Copyright ... ... (See below.)
5 * Copyright 2017 Serge Gautherie <reactos-git_serge_171003@gautherie.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Note: Most of this code comes from the old file "i386mem.c", which
22 * was Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
26 #include <arch/pc/x86common.h>
30 DBG_DEFAULT_CHANNEL(MEMORY
);
32 #define ULONGLONG_ALIGN_DOWN_BY(size, align) \
33 ((ULONGLONG)(size) & ~((ULONGLONG)(align) - 1))
35 #define ULONGLONG_ALIGN_UP_BY(size, align) \
36 (ULONGLONG_ALIGN_DOWN_BY(((ULONGLONG)(size) + align - 1), align))
38 #define MAX_BIOS_DESCRIPTORS 80ul
40 BIOS_MEMORY_MAP PcBiosMemoryMap
[MAX_BIOS_DESCRIPTORS
];
43 FREELDR_MEMORY_DESCRIPTOR PcMemoryMap
[MAX_BIOS_DESCRIPTORS
+ 1];
48 IN OUT PFREELDR_MEMORY_DESCRIPTOR List
,
50 IN PFN_NUMBER BasePage
,
51 IN PFN_NUMBER PageCount
,
52 IN TYPE_OF_MEMORY MemoryType
);
56 GetExtendedMemoryConfiguration(ULONG
* pMemoryAtOneMB
/* in KB */, ULONG
* pMemoryAtSixteenMB
/* in 64KB */)
61 TRACE("GetExtendedMemoryConfiguration()\n");
64 *pMemoryAtSixteenMB
= 0;
67 // Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS
71 // CF clear if successful
72 // AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
73 // BX = extended memory above 16M, in 64K blocks
74 // CX = configured memory 1M to 16M, in K
75 // DX = configured memory above 16M, in 64K blocks
78 Int386(0x15, &RegsIn
, &RegsOut
);
80 TRACE("Int15h AX=E801h\n");
81 TRACE("AX = 0x%x\n", RegsOut
.w
.ax
);
82 TRACE("BX = 0x%x\n", RegsOut
.w
.bx
);
83 TRACE("CX = 0x%x\n", RegsOut
.w
.cx
);
84 TRACE("DX = 0x%x\n", RegsOut
.w
.dx
);
85 TRACE("CF set = %s\n", (RegsOut
.x
.eflags
& EFLAGS_CF
) ? "TRUE" : "FALSE");
87 if (INT386_SUCCESS(RegsOut
))
89 // If AX=BX=0000h the use CX and DX
90 if (RegsOut
.w
.ax
== 0)
92 // Return extended memory size in K
93 *pMemoryAtSixteenMB
= RegsOut
.w
.dx
;
94 *pMemoryAtOneMB
= RegsOut
.w
.cx
;
99 // Return extended memory size in K
100 *pMemoryAtSixteenMB
= RegsOut
.w
.bx
;
101 *pMemoryAtOneMB
= RegsOut
.w
.ax
;
106 // If we get here then Int15 Func E801h didn't work
107 // So try Int15 Func 88h
109 // SYSTEM - GET EXTENDED MEMORY SIZE (286+)
113 // CF clear if successful
114 // AX = number of contiguous KB starting at absolute address 100000h
117 // 80h invalid command (PC,PCjr)
118 // 86h unsupported function (XT,PS30)
120 Int386(0x15, &RegsIn
, &RegsOut
);
122 TRACE("Int15h AH=88h\n");
123 TRACE("AX = 0x%x\n", RegsOut
.w
.ax
);
124 TRACE("CF set = %s\n", (RegsOut
.x
.eflags
& EFLAGS_CF
) ? "TRUE" : "FALSE");
126 if (INT386_SUCCESS(RegsOut
) && RegsOut
.w
.ax
!= 0)
128 *pMemoryAtOneMB
= RegsOut
.w
.ax
;
132 // If we get here then Int15 Func 88h didn't work
133 // So try reading the CMOS
134 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x31);
135 *pMemoryAtOneMB
= READ_PORT_UCHAR((PUCHAR
)0x71);
136 *pMemoryAtOneMB
= (*pMemoryAtOneMB
& 0xFFFF);
137 *pMemoryAtOneMB
= (*pMemoryAtOneMB
<< 8);
139 TRACE("Int15h Failed\n");
140 TRACE("CMOS reports: 0x%lx\n", *pMemoryAtOneMB
);
142 if (*pMemoryAtOneMB
!= 0)
152 PcMemGetConventionalMemorySize(VOID
)
156 TRACE("PcMemGetConventionalMemorySize()\n");
159 * BIOS - GET MEMORY SIZE
162 * AX = kilobytes of contiguous memory starting at absolute address 00000h
164 * This call returns the contents of the word at 0040h:0013h;
165 * in PC and XT, this value is set from the switches on the motherboard
168 Int386(0x12, &Regs
, &Regs
);
171 TRACE("AX = 0x%x\n", Regs
.w
.ax
);
173 return (ULONG
)Regs
.w
.ax
;
184 TRACE("GetEbdaLocation()\n");
186 /* Get the address of the Extended BIOS Data Area (EBDA).
188 * SYSTEM - RETURN EXTENDED-BIOS DATA-AREA SEGMENT ADDRESS (PS)
192 * CF clear if successful
193 * ES = segment of data area
195 Regs
.x
.eax
= 0x0000C100;
196 Int386(0x15, &Regs
, &Regs
);
198 /* If the function fails, there is no EBDA */
199 if (!INT386_SUCCESS(Regs
))
204 /* Get Base address and (maximum) size */
205 *BaseAddress
= (ULONG
)Regs
.w
.es
<< 4;
206 *Size
= 0xA0000 - *BaseAddress
;
212 PcMemCheckUsableMemorySize(VOID
)
214 ULONG Size
, RequiredSize
;
216 TRACE("PcMemCheckUsableMemorySize()\n");
218 /* Make sure the usable memory is large enough. To do this we check the 16
219 bit value at address 0x413 inside the BDA, which gives us the usable size
221 Size
= (*(PUSHORT
)(ULONG_PTR
)0x413) * 1024;
222 RequiredSize
= FREELDR_BASE
+ FrLdrImageSize
+ PAGE_SIZE
;
223 if (Size
< RequiredSize
)
225 FrLdrBugCheckWithMessage(
229 "The BIOS reported a usable memory range up to 0x%lx, which is too small!\n"
230 "Required size is 0x%lx\n\n"
231 "If you see this, please report to the ReactOS team!",
238 PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap
, ULONG MaxMemoryMapSize
)
241 ULONGLONG RealBaseAddress
, EndAddress
, RealSize
;
242 TYPE_OF_MEMORY MemoryType
;
244 ASSERT(PcBiosMapCount
== 0);
246 TRACE("PcMemGetBiosMemoryMap()\n");
249 * Newer BIOSes - GET SYSTEM MEMORY MAP
253 * EDX = 534D4150h ('SMAP')
254 * EBX = continuation value or 00000000h to start at beginning of map
255 * ECX = size of buffer for result, in bytes (should be >= 20 bytes)
256 * ES:DI -> buffer for result
258 * CF clear if successful
259 * EAX = 534D4150h ('SMAP')
260 * ES:DI buffer filled
261 * EBX = next offset from which to copy or 00000000h if all done
262 * ECX = actual length returned in bytes
264 * AH = error code (86h)
266 Regs
.x
.ebx
= 0x00000000;
268 while (PcBiosMapCount
< MAX_BIOS_DESCRIPTORS
)
270 /* ACPI 3.0/4.0: Set Extended Attributes to enabled/valid by default, in case entry has no E.A.. */
271 ((PBIOS_MEMORY_MAP
)BIOSCALLBUFFER
)->ExtendedAttributesAsULONG
= 0;
272 ((PBIOS_MEMORY_MAP
)BIOSCALLBUFFER
)->ExtendedAttributes
.Enabled_Reserved
= 1;
274 /* Setup the registers for the BIOS call */
275 Regs
.x
.eax
= 0x0000E820;
276 Regs
.x
.edx
= 0x534D4150; /* ('SMAP') */
277 /* Regs.x.ebx = 0x00000001; Continuation value already set */
278 Regs
.x
.ecx
= sizeof(BIOS_MEMORY_MAP
);
279 Regs
.w
.es
= BIOSCALLBUFSEGMENT
;
280 Regs
.w
.di
= BIOSCALLBUFOFFSET
;
281 Int386(0x15, &Regs
, &Regs
);
283 TRACE("Memory Map Entry %lu\n", PcBiosMapCount
);
284 TRACE("Int15h AX=E820h\n");
285 TRACE("EAX = 0x%lx\n", Regs
.x
.eax
);
286 TRACE("EBX = 0x%lx\n", Regs
.x
.ebx
);
287 TRACE("ECX = %lu\n", Regs
.x
.ecx
);
288 TRACE("CF set = %s\n", (Regs
.x
.eflags
& EFLAGS_CF
) ? "TRUE" : "FALSE");
290 /* If the BIOS didn't return 'SMAP' in EAX then
291 * it doesn't support this call. */
292 if (Regs
.x
.eax
!= 0x534D4150)
294 WARN("BIOS doesn't support Int15h AX=E820h!\n");
298 /* If the carry flag is set,
299 * then this call was past the last entry, so we're done. */
300 if (!INT386_SUCCESS(Regs
))
302 TRACE("End of System Memory Map! (Past last)\n");
308 TRACE("Discard empty entry. (would-be-PcBiosMapCount = %lu)\n",
313 /* Extra safety: unexpected entry length.
314 * All in-between values are valid too, as x86 is little-indian
315 * and only lower byte is used per ACPI 6.2-A.
317 if (Regs
.x
.ecx
< RTL_SIZEOF_THROUGH_FIELD(BIOS_MEMORY_MAP
, Type
) ||
318 Regs
.x
.ecx
> sizeof(BIOS_MEMORY_MAP
))
320 ERR("Int 15h AX=E820h returned an invalid entry length! (would-be-PcBiosMapCount = %lu, Entry length = (%Iu <=) %lu (<= %Iu))\n",
321 PcBiosMapCount
, RTL_SIZEOF_THROUGH_FIELD(BIOS_MEMORY_MAP
, Type
), Regs
.x
.ecx
, sizeof(BIOS_MEMORY_MAP
));
322 /* Warn user, unless wrong case is "first and not too big entry", which is otherwise harmless. */
323 if (PcBiosMapCount
> 0 || Regs
.x
.ecx
> sizeof(BIOS_MEMORY_MAP
))
325 ASSERTMSG("Int 15h AX=E820h returned an invalid entry length!\n", FALSE
);
327 /* We keep previous entries (if any), but do not dare trying next entries.
328 * We assume these entries are good to use as is. If they are not, we are in trouble...
329 * (And don't ask what happens if BIOS actually overflowed our entry buffer...)
331 * FIXME: Safer = revert previous entries, Safest = blacklist this BIOS.
336 if (((PBIOS_MEMORY_MAP
)BIOSCALLBUFFER
)->ExtendedAttributes
.Enabled_Reserved
== 0)
338 WARN("Discard disabled/invalid entry. (would-be-PcBiosMapCount = %lu)\n",
340 /* This unlikely case was correct between ACPI 3.0 and 4.0, so assume all is fine.
341 * Unless we would be ready to drop ACPI 3.0 compatibility.
346 /* Copy data to global buffer */
347 RtlCopyMemory(&PcBiosMemoryMap
[PcBiosMapCount
], (PVOID
)BIOSCALLBUFFER
, sizeof(BIOS_MEMORY_MAP
));
349 TRACE("BaseAddress: 0x%llx\n", PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
);
350 TRACE("Length: 0x%llx\n", PcBiosMemoryMap
[PcBiosMapCount
].Length
);
351 TRACE("Type: 0x%lx\n", PcBiosMemoryMap
[PcBiosMapCount
].Type
);
352 TRACE("ExtendedAttributesAsULONG: 0x%08lx\n", PcBiosMemoryMap
[PcBiosMapCount
].ExtendedAttributesAsULONG
);
354 if (PcBiosMemoryMap
[PcBiosMapCount
].ExtendedAttributes
.ErrorLog
== 1)
356 FIXME("EA.ErrorLog = 1. Please report this to CORE-14150. "
357 "(PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx, Type = 0x%lx, ExtendedAttributesAsULONG = 0x%08lx)\n",
359 PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
,
360 PcBiosMemoryMap
[PcBiosMapCount
].Length
,
361 PcBiosMemoryMap
[PcBiosMapCount
].Type
,
362 PcBiosMemoryMap
[PcBiosMapCount
].ExtendedAttributesAsULONG
);
363 // NotWantedForPublicBuilds: ASSERTMSG("EA.ErrorLog = 1. Check/Report then CONTinue.\n", FALSE);
366 if (PcBiosMemoryMap
[PcBiosMapCount
].Length
== 0)
368 TRACE("Discard empty range. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0)\n",
369 PcBiosMapCount
, PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
);
373 /* Check if this is free memory */
374 if (PcBiosMemoryMap
[PcBiosMapCount
].Type
== BiosMemoryUsable
)
376 MemoryType
= LoaderFree
;
378 /* Align up base of memory range */
379 RealBaseAddress
= ULONGLONG_ALIGN_UP_BY(
380 PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
,
383 /* Calculate aligned EndAddress */
384 EndAddress
= PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
+
385 PcBiosMemoryMap
[PcBiosMapCount
].Length
;
386 EndAddress
= ULONGLONG_ALIGN_DOWN_BY(EndAddress
, PAGE_SIZE
);
388 /* Check if there is anything left */
389 if (EndAddress
<= RealBaseAddress
)
391 /* This doesn't span any page, so continue with next range */
392 TRACE("Skipping aligned range < PAGE_SIZE. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
394 PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
,
395 PcBiosMemoryMap
[PcBiosMapCount
].Length
);
399 /* Calculate the length of the aligned range */
400 RealSize
= EndAddress
- RealBaseAddress
;
404 if (PcBiosMemoryMap
[PcBiosMapCount
].Type
== BiosMemoryReserved
)
406 MemoryType
= LoaderFirmwarePermanent
;
410 MemoryType
= LoaderSpecialMemory
;
413 /* Align down base of memory area */
414 RealBaseAddress
= ULONGLONG_ALIGN_DOWN_BY(
415 PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
,
418 /* Calculate the length after aligning the base */
419 RealSize
= PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
+
420 PcBiosMemoryMap
[PcBiosMapCount
].Length
- RealBaseAddress
;
421 RealSize
= ULONGLONG_ALIGN_UP_BY(RealSize
, PAGE_SIZE
);
424 /* Check if we can add this descriptor */
425 if (RealSize
< MM_PAGE_SIZE
)
427 TRACE("Skipping aligned range < MM_PAGE_SIZE. (PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
429 PcBiosMemoryMap
[PcBiosMapCount
].BaseAddress
,
430 PcBiosMemoryMap
[PcBiosMapCount
].Length
);
432 else if (PcMapCount
>= MaxMemoryMapSize
)
434 ERR("PcMemoryMap is already full! (PcBiosMapCount = %lu, PcMapCount = %lu (>= %lu))\n",
435 PcBiosMapCount
, PcMapCount
, MaxMemoryMapSize
);
436 // NotWantedForPublicBuilds: ASSERTMSG("PcMemoryMap is already full!\n", FALSE);
437 /* We keep previous entries, and half-retrieve current/next entries.
438 * We assume all these entries are good to use as is. If they are not, we are in trouble...
440 * FIXME: Safer = revert (half-)retrieved entries, Safest = increase MaxMemoryMapSize.
445 /* Add the descriptor */
446 PcMapCount
= AddMemoryDescriptor(PcMemoryMap
,
447 MAX_BIOS_DESCRIPTORS
,
448 (PFN_NUMBER
)(RealBaseAddress
/ MM_PAGE_SIZE
),
449 (PFN_NUMBER
)(RealSize
/ MM_PAGE_SIZE
),
456 /* If the continuation value is zero,
457 * then this was the last entry, so we're done. */
458 if (Regs
.x
.ebx
== 0x00000000)
460 TRACE("End of System Memory Map! (Reset)\n");
464 /* Check whether there would be more entries to process. */
465 if (PcBiosMapCount
>= MAX_BIOS_DESCRIPTORS
&& Regs
.x
.ebx
!= 0x00000000)
467 ERR("PcBiosMemoryMap is already full! (PcBiosMapCount = %lu (>= %lu), PcMapCount = %lu)\n",
468 PcBiosMapCount
, MAX_BIOS_DESCRIPTORS
, PcMapCount
);
469 // NotWantedForPublicBuilds: ASSERTMSG("PcBiosMemoryMap is already full!\n", FALSE);
470 /* We keep retrieved entries, but ignore next entries.
471 * We assume these entries are good to use as is. If they are not, we are in trouble...
473 * FIXME: Safer = revert retrieved entries, Safest = increase MAX_BIOS_DESCRIPTORS.
477 TRACE("PcMemGetBiosMemoryMap end: PcBiosMapCount = %lu\n", PcBiosMapCount
);
478 return PcBiosMapCount
;
483 ULONG_PTR BaseAddress
,
485 TYPE_OF_MEMORY MemoryType
,
488 ULONG_PTR BasePage
, PageCount
;
491 BasePage
= BaseAddress
/ PAGE_SIZE
;
492 PageCount
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress
, Size
);
494 for (i
= 0; i
< PcMapCount
; i
++)
496 /* Check for conflicting descriptor */
497 if ((PcMemoryMap
[i
].BasePage
< BasePage
+ PageCount
) &&
498 (PcMemoryMap
[i
].BasePage
+ PcMemoryMap
[i
].PageCount
> BasePage
))
500 /* Check if the memory is free */
501 if (PcMemoryMap
[i
].MemoryType
!= LoaderFree
)
503 FrLdrBugCheckWithMessage(
507 "Failed to reserve memory in the range 0x%Ix - 0x%Ix for %s",
515 /* Add the memory descriptor */
516 PcMapCount
= AddMemoryDescriptor(PcMemoryMap
,
517 MAX_BIOS_DESCRIPTORS
,
525 ULONG_PTR BaseAddress
,
527 TYPE_OF_MEMORY MemoryType
)
529 ULONG_PTR BasePage
, PageCount
;
531 BasePage
= BaseAddress
/ PAGE_SIZE
;
532 PageCount
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress
, Size
);
534 /* Add the memory descriptor */
535 PcMapCount
= AddMemoryDescriptor(PcMemoryMap
,
536 MAX_BIOS_DESCRIPTORS
,
542 PFREELDR_MEMORY_DESCRIPTOR
543 PcMemGetMemoryMap(ULONG
*MemoryMapSize
)
546 ULONG ExtendedMemorySizeAtOneMB
;
547 ULONG ExtendedMemorySizeAtSixteenMB
;
548 ULONG EbdaBase
, EbdaSize
;
550 TRACE("PcMemGetMemoryMap()\n");
552 PcMemCheckUsableMemorySize();
554 EntryCount
= PcMemGetBiosMemoryMap(PcMemoryMap
, MAX_BIOS_DESCRIPTORS
);
556 /* If the BIOS didn't provide a memory map, synthesize one */
559 GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB
,
560 &ExtendedMemorySizeAtSixteenMB
);
562 /* Conventional memory */
563 AddMemoryDescriptor(PcMemoryMap
,
564 MAX_BIOS_DESCRIPTORS
,
566 PcMemGetConventionalMemorySize() * 1024 / PAGE_SIZE
,
569 /* Extended memory */
570 PcMapCount
= AddMemoryDescriptor(PcMemoryMap
,
571 MAX_BIOS_DESCRIPTORS
,
572 1024 * 1024 / PAGE_SIZE
,
573 ExtendedMemorySizeAtOneMB
* 1024 / PAGE_SIZE
,
576 if (ExtendedMemorySizeAtSixteenMB
!= 0)
578 /* Extended memory at 16MB */
579 PcMapCount
= AddMemoryDescriptor(PcMemoryMap
,
580 MAX_BIOS_DESCRIPTORS
,
581 0x1000000 / PAGE_SIZE
,
582 ExtendedMemorySizeAtSixteenMB
* 64 * 1024 / PAGE_SIZE
,
586 /* Check if we have an EBDA and get it's location */
587 if (GetEbdaLocation(&EbdaBase
, &EbdaSize
))
589 /* Add the descriptor */
590 PcMapCount
= AddMemoryDescriptor(PcMemoryMap
,
591 MAX_BIOS_DESCRIPTORS
,
592 (EbdaBase
/ PAGE_SIZE
),
593 ADDRESS_AND_SIZE_TO_SPAN_PAGES(EbdaBase
, EbdaSize
),
594 LoaderFirmwarePermanent
);
598 /* Setup some protected ranges */
599 SetMemory(0x000000, 0x01000, LoaderFirmwarePermanent
); // Realmode IVT / BDA
600 SetMemory(0x0A0000, 0x50000, LoaderFirmwarePermanent
); // Video memory
601 SetMemory(0x0F0000, 0x10000, LoaderSpecialMemory
); // ROM
602 SetMemory(0xFFF000, 0x01000, LoaderSpecialMemory
); // unusable memory (do we really need this?)
604 /* Reserve some static ranges for freeldr */
605 ReserveMemory(0x1000, STACKLOW
- 0x1000, LoaderFirmwareTemporary
, "BIOS area");
606 ReserveMemory(STACKLOW
, STACKADDR
- STACKLOW
, LoaderOsloaderStack
, "FreeLdr stack");
607 ReserveMemory(FREELDR_BASE
, FrLdrImageSize
, LoaderLoadedProgram
, "FreeLdr image");
609 /* Default to 1 page above freeldr for the disk read buffer */
610 DiskReadBuffer
= (PUCHAR
)ALIGN_UP_BY(FREELDR_BASE
+ FrLdrImageSize
, PAGE_SIZE
);
611 DiskReadBufferSize
= PAGE_SIZE
;
613 /* Scan for free range above freeldr image */
614 for (i
= 0; i
< PcMapCount
; i
++)
616 if ((PcMemoryMap
[i
].BasePage
> (FREELDR_BASE
/ PAGE_SIZE
)) &&
617 (PcMemoryMap
[i
].MemoryType
== LoaderFree
))
619 /* Use this range for the disk read buffer */
620 DiskReadBuffer
= (PVOID
)(PcMemoryMap
[i
].BasePage
* PAGE_SIZE
);
621 DiskReadBufferSize
= min(PcMemoryMap
[i
].PageCount
* PAGE_SIZE
,
622 MAX_DISKREADBUFFER_SIZE
);
627 TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
628 DiskReadBuffer
, DiskReadBufferSize
);
630 /* Now reserve the range for the disk read buffer */
631 ReserveMemory((ULONG_PTR
)DiskReadBuffer
,
633 LoaderFirmwareTemporary
,
636 TRACE("Dumping resulting memory map:\n");
637 for (i
= 0; i
< PcMapCount
; i
++)
639 TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
640 PcMemoryMap
[i
].BasePage
,
641 PcMemoryMap
[i
].PageCount
,
642 MmGetSystemMemoryMapTypeString(PcMemoryMap
[i
].MemoryType
));
645 *MemoryMapSize
= PcMapCount
;