https://git.reactos.org/?p=reactos.git;a=commitdiff;h=74f92c3d867a2d827e00e…
commit 74f92c3d867a2d827e00e70dcf6e0295c40465c0
Author: Serge Gautherie <32623169+SergeGautherie(a)users.noreply.github.com>
AuthorDate: Wed Dec 27 11:09:20 2017 +0100
CORE-13332. PcMemGetBiosMemoryMap(): Update ACPI (Extended Attributes) support.
(#143)
[FREELDR] Update ACPI (Extended Attributes) support in PcMemGetBiosMemoryMap()
CORE-13332
* PcMemGetBiosMemoryMap(): Add Extended Attributes set and check for entry validity
and default handling of unexpected case.
* pcbios.h: Rename superceded BIOS_MEMORY_MAP.Reserved. Adapt existing code to new
ACPI 6.2-A definitions.
* pcbios.h: Update BIOS_MEMORY_TYPE and BIOS_MEMORY_MAP to ACPI 6.2-A from 1.0+.
* PcMemGetBiosMemoryMap(): Misc fixes, no functional changes.
*Create PcMemCheckUsableMemorySize(), to split unrelated code out.
*Fix a copypasta in 2 output strings from ba9a1c3abba3b795a55186f289704ec8eeaf1cb9.
*Improve output readability of TRACE("ECX ...", ...).
*Move a TRACE("\n").
*Improve code style a bit.
---
boot/freeldr/freeldr/arch/i386/pcmem.c | 63 ++++++++++++++++++++-------
boot/freeldr/freeldr/include/arch/pc/pcbios.h | 51 ++++++++++++++++++----
2 files changed, 89 insertions(+), 25 deletions(-)
diff --git a/boot/freeldr/freeldr/arch/i386/pcmem.c
b/boot/freeldr/freeldr/arch/i386/pcmem.c
index 9b0997ebf5..5741a8414c 100644
--- a/boot/freeldr/freeldr/arch/i386/pcmem.c
+++ b/boot/freeldr/freeldr/arch/i386/pcmem.c
@@ -1,6 +1,9 @@
/*
* FreeLoader
*
+ * Copyright ... ... (See below.)
+ * Copyright 2017 Serge Gautherie
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -145,7 +148,8 @@ GetExtendedMemoryConfiguration(ULONG* pMemoryAtOneMB /* in KB */,
ULONG* pMemory
return FALSE;
}
-static ULONG
+static
+ULONG
PcMemGetConventionalMemorySize(VOID)
{
REGS Regs;
@@ -203,18 +207,11 @@ GetEbdaLocation(
}
static
-ULONG
-PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
+VOID
+PcMemCheckUsableMemorySize(VOID)
{
- REGS Regs;
- ULONGLONG RealBaseAddress, EndAddress, RealSize;
- TYPE_OF_MEMORY MemoryType;
ULONG Size, RequiredSize;
- ASSERT(PcBiosMapCount == 0);
-
- TRACE("PcMemGetBiosMemoryMap()\n");
-
/* Make sure the usable memory is large enough. To do this we check the 16
bit value at address 0x413 inside the BDA, which gives us the usable size
in KB */
@@ -231,6 +228,19 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG
MaxMemoryMapSi
"If you see this, please report to the ReactOS team!",
Size, RequiredSize);
}
+}
+
+static
+ULONG
+PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
+{
+ REGS Regs;
+ ULONGLONG RealBaseAddress, EndAddress, RealSize;
+ TYPE_OF_MEMORY MemoryType;
+
+ ASSERT(PcBiosMapCount == 0);
+
+ TRACE("PcMemGetBiosMemoryMap()\n");
/* Int 15h AX=E820h
* Newer BIOSes - GET SYSTEM MEMORY MAP
@@ -254,6 +264,10 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG
MaxMemoryMapSi
while (PcBiosMapCount < MAX_BIOS_DESCRIPTORS)
{
+ /* ACPI 3.0/4.0: Set Extended Attributes to enabled/valid by default, in case
entry has no E.A.. */
+ ((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributesAsULONG = 0;
+ ((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributes.Enabled_Reserved = 1;
+
/* Setup the registers for the BIOS call */
Regs.x.eax = 0x0000E820;
Regs.x.edx = 0x534D4150; /* ('SMAP') */
@@ -267,7 +281,7 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG
MaxMemoryMapSi
TRACE("Int15h AX=E820h\n");
TRACE("EAX = 0x%lx\n", Regs.x.eax);
TRACE("EBX = 0x%lx\n", Regs.x.ebx);
- TRACE("ECX = 0x%lx\n", Regs.x.ecx);
+ TRACE("ECX = %lu\n", Regs.x.ecx);
TRACE("CF set = %s\n", (Regs.x.eflags & EFLAGS_CF) ?
"TRUE" : "FALSE");
/* If the BIOS didn't return 'SMAP' in EAX then
@@ -316,14 +330,23 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG
MaxMemoryMapSi
break;
}
+ if (((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributes.Enabled_Reserved ==
0)
+ {
+ WARN("Discard disabled/invalid entry. (would-be-PcBiosMapCount =
%lu)\n",
+ PcBiosMapCount);
+ /* This unlikely case was correct between ACPI 3.0 and 4.0, so assume all is
fine.
+ * Unless we would be ready to drop ACPI 3.0 compatibility.
+ */
+ goto nextRange;
+ }
+
/* Copy data to global buffer */
- RtlCopyMemory(&PcBiosMemoryMap[PcBiosMapCount], (PVOID)BIOSCALLBUFFER,
Regs.x.ecx);
+ RtlCopyMemory(&PcBiosMemoryMap[PcBiosMapCount], (PVOID)BIOSCALLBUFFER,
sizeof(BIOS_MEMORY_MAP));
TRACE("BaseAddress: 0x%llx\n",
PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
TRACE("Length: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].Length);
TRACE("Type: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Type);
- TRACE("Reserved: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Reserved);
- TRACE("\n");
+ TRACE("ExtendedAttributesAsULONG: 0x%08lx\n",
PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributesAsULONG);
if (PcBiosMemoryMap[PcBiosMapCount].Length == 0)
{
@@ -364,9 +387,13 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG
MaxMemoryMapSi
else
{
if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryReserved)
+ {
MemoryType = LoaderFirmwarePermanent;
+ }
else
+ {
MemoryType = LoaderSpecialMemory;
+ }
/* Align down base of memory area */
RealBaseAddress = ULONGLONG_ALIGN_DOWN_BY(
@@ -411,6 +438,8 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG
MaxMemoryMapSi
PcBiosMapCount++;
nextRange:
+ TRACE("\n");
+
/* If the continuation value is zero,
* then this was the last entry, so we're done. */
if (Regs.x.ebx == 0x00000000)
@@ -422,9 +451,9 @@ nextRange:
/* Check whether there would be more entries to process. */
if (PcBiosMapCount >= MAX_BIOS_DESCRIPTORS && Regs.x.ebx != 0x00000000)
{
- ERR("PcBiosMapCount is already full! (PcBiosMapCount = %lu (>= %lu),
PcMapCount = %lu)\n",
+ ERR("PcBiosMemoryMap is already full! (PcBiosMapCount = %lu (>= %lu),
PcMapCount = %lu)\n",
PcBiosMapCount, MAX_BIOS_DESCRIPTORS, PcMapCount);
- // NotWantedForPublicBuilds: ASSERTMSG("PcBiosMapCount is already
full!", FALSE);
+ // NotWantedForPublicBuilds: ASSERTMSG("PcBiosMemoryMap is already
full!", FALSE);
/* We keep retrieved entries, but ignore next entries.
* We assume these entries are good to use as is. If they are not, we are in
trouble...
*
@@ -507,6 +536,8 @@ PcMemGetMemoryMap(ULONG *MemoryMapSize)
TRACE("PcMemGetMemoryMap()\n");
+ PcMemCheckUsableMemorySize();
+
EntryCount = PcMemGetBiosMemoryMap(PcMemoryMap, MAX_BIOS_DESCRIPTORS);
/* If the BIOS didn't provide a memory map, synthesize one */
diff --git a/boot/freeldr/freeldr/include/arch/pc/pcbios.h
b/boot/freeldr/freeldr/include/arch/pc/pcbios.h
index b60df0b122..826a16854d 100644
--- a/boot/freeldr/freeldr/include/arch/pc/pcbios.h
+++ b/boot/freeldr/freeldr/include/arch/pc/pcbios.h
@@ -5,22 +5,55 @@
typedef enum
{
- BiosMemoryUsable=1,
- BiosMemoryReserved,
- BiosMemoryAcpiReclaim,
- BiosMemoryAcpiNvs
+ // ACPI 1.0.
+ BiosMemoryUsable = 1,
+ BiosMemoryReserved = 2,
+ BiosMemoryAcpiReclaim = 3,
+ BiosMemoryAcpiNvs = 4,
+ // ACPI 3.0.
+ BiosMemoryUnusable = 5,
+ // ACPI 4.0.
+ BiosMemoryDisabled = 6,
+ // ACPI 6.0.
+ BiosMemoryPersistent = 7,
+ BiosMemoryUndefined08 = 8,
+ BiosMemoryUndefined09 = 9,
+ BiosMemoryUndefined10 = 10,
+ BiosMemoryUndefined11 = 11,
+ BiosMemoryOemDefined12 = 12
+ // BiosMemoryUndefinedNN = 13-0xEFFFFFFF
+ // BiosMemoryOemDefinedNN = 0xF0000000-0xFFFFFFFF
} BIOS_MEMORY_TYPE;
typedef struct
{
- ULONGLONG BaseAddress;
- ULONGLONG Length;
- ULONG Type;
- ULONG Reserved;
+ // ACPI 1.0.
+ ULONGLONG BaseAddress;
+ ULONGLONG Length;
+ ULONG Type;
+ // ACPI 3.0.
+ union
+ {
+ ULONG ExtendedAttributesAsULONG;
+
+ struct
+ {
+ // Bit 0. ACPI 3.0. As of ACPI 4.0, became "Reserved -> must be
1".
+ ULONG Enabled_Reserved : 1;
+ // Bit 1. ACPI 3.0. As of ACPI 6.1, became "Unimplemented ->
Deprecated".
+ ULONG NonVolatile_Deprecated : 1;
+ // Bit 2. ACPI 4.0. As of ACPI 6.1, became "Unimplemented ->
Deprecated".
+ ULONG SlowAccess_Deprecated : 1;
+ // Bit 3. ACPI 4.0. ACPI 5.0-A added "Used only on PC-AT BIOS" (not
UEFI).
+ ULONG ErrorLog : 1;
+ // Bits 4-31. ACPI 3.0.
+ ULONG Reserved : 28;
+ } ExtendedAttributes;
+ };
} BIOS_MEMORY_MAP, *PBIOS_MEMORY_MAP;
/* Int 15h AX=E820h Entry minimal size. */
-C_ASSERT(FIELD_OFFSET(BIOS_MEMORY_MAP, Reserved) == 20);
+C_ASSERT(FIELD_OFFSET(BIOS_MEMORY_MAP, ExtendedAttributes) == 20);
/* Int 15h AX=E820h Entry maximal size. */
C_ASSERT(sizeof(BIOS_MEMORY_MAP) == 24);