From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ej1-f44.google.com (mail-ej1-f44.google.com [209.85.218.44]) by mx.groups.io with SMTP id smtpd.web09.9052.1623763380209406115 for ; Tue, 15 Jun 2021 06:23:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@9elements.com header.s=google header.b=buxz6J+E; spf=pass (domain: 9elements.com, ip: 209.85.218.44, mailfrom: patrick.rudolph@9elements.com) Received: by mail-ej1-f44.google.com with SMTP id hq2so441661ejc.2 for ; Tue, 15 Jun 2021 06:22:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=9elements.com; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=3V3nfXHU4UZvt3T8cm4Df5GlzSZfwETOqx+U0FYMxqc=; b=buxz6J+EWlaLnB6FCTc5tSQFAVSQDB4d/G8VIln3rZ+W/YuU18O4etKfRG0kOq9MEi KwMwJ42722CqtB6qEcI4WX47ZiF+p822Duf1zJ8u5MLNUnTiQfYH5As5CWepIhWkTH0q wMenv52KKpI4tnRq1NZm8Gvw5aOOYCjBzQMeOXspFWtgBNrmPlhCXPQBmeSEzwQVbqXM /+dJgFJKXyc5lE3Qi4ODVVEbkDTVW+FCdzR4TwMpIGM1SLe00rxG2oNG+mLYIdaa0ORH l/zkX7HZOSElLgG2Mhus+0dkvNC2kRoruNb0b7vFBZkqzzYXUM1HZnRlle8whqCPdirU NpcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=3V3nfXHU4UZvt3T8cm4Df5GlzSZfwETOqx+U0FYMxqc=; b=HNWfa4fISlyE1zjpFhLZKmICus6qvirzhtvVqtQM5TxjQNyKdlFrUyibcpqc2lut3T G4vVc6dTM4A8mlGNkip5LSyahCFtol+Y2DPnQtobmCoN51N/dgsD7B6Rm1hwTEXa4NeM RqRi33rAlqanC4wAht6IwQmBzol1Ikkgk+qwxIki8m2V//7Wy4rpDtY1bw4jA1+DgzSr AKV1tkLR2JH59IZEITAH9W9AtsPyJ+H9P/yBJF6vKLnjpOZ2TWgjj/Ha8dcB95BAWUTc e64pAUf9XWw1MSau64offqMPixk8HoPfq8u9H54M6v3qENbEZWCSRYsH/tFfxKGDT5O1 MCDQ== X-Gm-Message-State: AOAM532t34cGBqM03HqfJi5jF8cZZB7/Ykr85dV5XcZDpb4EfPVILTks e8teskWFKEL5htxoQ1TwmvWLUdXCrpViX23d X-Google-Smtp-Source: ABdhPJyt0KZhuallDfa1J7sWDn8RnrNdAXoDNezzG0QXfkBMpHK2W9xxinMVvQ0jFoCvrIWdjusDtg== X-Received: by 2002:a17:907:1b20:: with SMTP id mp32mr20875599ejc.495.1623763375880; Tue, 15 Jun 2021 06:22:55 -0700 (PDT) Return-Path: Received: from rudolphp-notebook.sr1.9esec.dev (ip-178-202-79-247.hsi09.unitymediagroup.de. [178.202.79.247]) by smtp.gmail.com with ESMTPSA id q5sm7433798ejc.117.2021.06.15.06.22.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Jun 2021 06:22:55 -0700 (PDT) From: "Patrick Rudolph" To: devel@edk2.groups.io Cc: maurice.ma@intel.com, guo.dong@intel.com, benjamin.you@intel.com Subject: [PATCH] UefiPayloadPkg/UefiPayloadEntry: Improve bootloader memrange parsing Date: Tue, 15 Jun 2021 15:22:54 +0200 Message-Id: <20210615132254.3364910-1-patrick.rudolph@9elements.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Currently several DXE crash due to invalid memory resource settings. coreboot and slimbootloader provide an e820 compatible memory map, which doesn't work well with EDK2 as the e820 spec is missing MMIO regions. In e820 'reserved' could either mean "DRAM used by boot firmware" or "MMIO in use and not detectable by OS". Guess Top of lower usable DRAM (TOLUD) by walking memory ranges and then mark everything reserved below TOLUD as DRAM and everything reserved above TOLUD as MMIO. This fixes several assertions seen in PciHostBridgeDxe. Signed-off-by: Patrick Rudolph --- .../UefiPayloadEntry/UefiPayloadEntry.c | 187 +++++++++++++++++- .../UefiPayloadEntry/UefiPayloadEntry.h | 10 + 2 files changed, 194 insertions(+), 3 deletions(-) diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c b/UefiPaylo= adPkg/UefiPayloadEntry/UefiPayloadEntry.c index 805f5448d9..d20e1a0862 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c +++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c @@ -7,10 +7,162 @@ =0D #include "UefiPayloadEntry.h"=0D =0D +STATIC UINT32 TopOfLowerUsableDram =3D 0;=0D +=0D /**=0D Callback function to build resource descriptor HOB=0D =0D This function build a HOB based on the memory map entry info.=0D + It creates only EFI_RESOURCE_MEMORY_MAPPED_IO and EFI_RESOURCE_MEMORY_R= ESERVED=0D + resources.=0D +=0D + @param MemoryMapEntry Memory map entry info got from bootloader= .=0D + @param Params A pointer to ACPI_BOARD_INFO.=0D +=0D + @retval RETURN_SUCCESS Successfully build a HOB.=0D + @retval EFI_INVALID_PARAMETER Invalid parameter provided.=0D +**/=0D +EFI_STATUS=0D +MemInfoCallbackMMIO (=0D + IN MEMROY_MAP_ENTRY *MemoryMapEntry,=0D + IN VOID *Params=0D + )=0D +{=0D + EFI_PHYSICAL_ADDRESS Base;=0D + EFI_RESOURCE_TYPE Type;=0D + UINT64 Size;=0D + EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;=0D + ACPI_BOARD_INFO *AcpiBoardInfo;=0D +=0D + AcpiBoardInfo =3D (ACPI_BOARD_INFO *)Params;=0D + if (AcpiBoardInfo =3D=3D NULL) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Skip types already handled in MemInfoCallback=0D + //=0D + if (MemoryMapEntry->Type =3D=3D E820_RAM || MemoryMapEntry->Type =3D=3D = E820_ACPI) {=0D + return RETURN_SUCCESS;=0D + }=0D +=0D + if (MemoryMapEntry->Base =3D=3D AcpiBoardInfo->PcieBaseAddress) {=0D + //=0D + // MMCONF is always MMIO=0D + //=0D + Type =3D EFI_RESOURCE_MEMORY_MAPPED_IO;=0D + } else if (MemoryMapEntry->Base < TopOfLowerUsableDram) {=0D + //=0D + // It's in DRAM and thus must be reserved=0D + //=0D + Type =3D EFI_RESOURCE_MEMORY_RESERVED;=0D + } else if (MemoryMapEntry->Base < 0x100000000ULL &&=0D + MemoryMapEntry->Base >=3D TopOfLowerUsableDram) {=0D + //=0D + // It's not in DRAM, must be MMIO=0D + //=0D + Type =3D EFI_RESOURCE_MEMORY_MAPPED_IO;=0D + } else {=0D + Type =3D EFI_RESOURCE_MEMORY_RESERVED;=0D + }=0D +=0D + Base =3D MemoryMapEntry->Base;=0D + Size =3D MemoryMapEntry->Size;=0D +=0D + Attribue =3D EFI_RESOURCE_ATTRIBUTE_PRESENT |=0D + EFI_RESOURCE_ATTRIBUTE_INITIALIZED |=0D + EFI_RESOURCE_ATTRIBUTE_TESTED |=0D + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;=0D +=0D + BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, = Size);=0D + DEBUG ((DEBUG_INFO , "buildhob: base =3D 0x%lx, size =3D 0x%lx, type =3D= 0x%x\n", Base, Size, Type));=0D +=0D + if (MemoryMapEntry->Type =3D=3D E820_NVS) {=0D + BuildMemoryAllocationHob (Base, Size, EfiACPIMemoryNVS);=0D + } else if (MemoryMapEntry->Type =3D=3D E820_UNUSABLE ||=0D + MemoryMapEntry->Type =3D=3D E820_DISABLED) {=0D + BuildMemoryAllocationHob (Base, Size, EfiUnusableMemory);=0D + } else if (MemoryMapEntry->Type =3D=3D E820_PMEM) {=0D + BuildMemoryAllocationHob (Base, Size, EfiPersistentMemory);=0D + }=0D +=0D + return RETURN_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + Callback function to find TOLUD (Top of Lower Usable DRAM)=0D +=0D + Estimate where TOLUD (Top of Lower Usable DRAM) resides. The exact posi= tion=0D + would require platform specific code.=0D +=0D + @param MemoryMapEntry Memory map entry info got from bootloader= .=0D + @param Params Not used for now.=0D +=0D + @retval RETURN_SUCCESS Successfully updated TopOfLowerUsableDram= .=0D +**/=0D +EFI_STATUS=0D +FindToludCallback (=0D + IN MEMROY_MAP_ENTRY *MemoryMapEntry,=0D + IN VOID *Params=0D + )=0D +{=0D + //=0D + // This code assumes that the memory map on this x86 machine below 4GiB = is continous=0D + // until TOLUD. In addition it assumes that the bootloader provided memo= ry tables have=0D + // no "holes" and thus the first memory range not covered by e820 marks = the end of=0D + // usable DRAM. In addition it's assumed that every reserved memory regi= on touching=0D + // usable RAM is also covering DRAM, everything else that is marked rese= rved thus must be=0D + // MMIO not detectable by bootloader/OS=0D + //=0D +=0D + //=0D + // Skip memory types not RAM or reserved=0D + //=0D + if (MemoryMapEntry->Type =3D=3D E820_NVS || MemoryMapEntry->Type =3D=3D = E820_UNUSABLE ||=0D + MemoryMapEntry->Type =3D=3D E820_DISABLED || MemoryMapEntry->Type =3D= =3D E820_PMEM) {=0D + return RETURN_SUCCESS;=0D + }=0D +=0D + //=0D + // Skip resources above 4GiB=0D + //=0D + if (MemoryMapEntry->Base >=3D 0x100000000ULL) {=0D + return RETURN_SUCCESS;=0D + }=0D +=0D + if ((MemoryMapEntry->Type =3D=3D E820_RAM) ||=0D + (MemoryMapEntry->Type =3D=3D E820_ACPI)) {=0D + //=0D + // It's usable DRAM. Update TOLUD.=0D + //=0D + if (TopOfLowerUsableDram < (MemoryMapEntry->Base + MemoryMapEntry->Siz= e)) {=0D + TopOfLowerUsableDram =3D MemoryMapEntry->Base + MemoryMapEntry->Size= ;=0D + }=0D + } else {=0D + //=0D + // It might be reserved DRAM or MMIO.=0D + //=0D + // If it touches usable DRAM at Base assume it's DRAM as well,=0D + // as it could be bootloader installed tables, TSEG, GTT, ...=0D + //=0D + if (TopOfLowerUsableDram =3D=3D MemoryMapEntry->Base) {=0D + TopOfLowerUsableDram =3D MemoryMapEntry->Base + MemoryMapEntry->Size= ;=0D + }=0D + }=0D +=0D + return RETURN_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + Callback function to build resource descriptor HOB=0D +=0D + This function build a HOB based on the memory map entry info.=0D + Only add EFI_RESOURCE_SYSTEM_MEMORY.=0D =0D @param MemoryMapEntry Memory map entry info got from bootloader= .=0D @param Params Not used for now.=0D @@ -28,7 +180,15 @@ MemInfoCallback ( UINT64 Size;=0D EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;=0D =0D - Type =3D (MemoryMapEntry->Type =3D=3D 1) ? EFI_RESOURCE_SYSTEM_MEMORY= : EFI_RESOURCE_MEMORY_RESERVED;=0D + //=0D + // Skip everything not known to be usable DRAM.=0D + // It will be added later.=0D + //=0D + if (MemoryMapEntry->Type !=3D E820_RAM && MemoryMapEntry->Type !=3D E820= _ACPI) {=0D + return RETURN_SUCCESS;=0D + }=0D +=0D + Type =3D EFI_RESOURCE_SYSTEM_MEMORY;=0D Base =3D MemoryMapEntry->Base;=0D Size =3D MemoryMapEntry->Size;=0D =0D @@ -40,7 +200,7 @@ MemInfoCallback ( EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |=0D EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;=0D =0D - if (Base >=3D BASE_4GB ) {=0D + if (Base >=3D BASE_4GB) {=0D // Remove tested attribute to avoid DXE core to dispatch driver to mem= ory above 4GB=0D Attribue &=3D ~EFI_RESOURCE_ATTRIBUTE_TESTED;=0D }=0D @@ -48,6 +208,10 @@ MemInfoCallback ( BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, = Size);=0D DEBUG ((DEBUG_INFO , "buildhob: base =3D 0x%lx, size =3D 0x%lx, type =3D= 0x%x\n", Base, Size, Type));=0D =0D + if (MemoryMapEntry->Type =3D=3D E820_ACPI) {=0D + BuildMemoryAllocationHob (Base, Size, EfiACPIReclaimMemory);=0D + }=0D +=0D return RETURN_SUCCESS;=0D }=0D =0D @@ -236,7 +400,16 @@ BuildHobFromBl ( EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *NewGfxDeviceInfo;=0D =0D //=0D - // Parse memory info and build memory HOBs=0D + // First find TOLUD=0D + //=0D + Status =3D ParseMemoryInfo (FindToludCallback, NULL);=0D + if (EFI_ERROR(Status)) {=0D + return Status;=0D + }=0D + DEBUG ((DEBUG_INFO , "Assuming TOLUD =3D 0x%x\n", TopOfLowerUsableDram))= ;=0D +=0D + //=0D + // Parse memory info and build memory HOBs for Usable RAM=0D //=0D Status =3D ParseMemoryInfo (MemInfoCallback, NULL);=0D if (EFI_ERROR(Status)) {=0D @@ -289,6 +462,14 @@ BuildHobFromBl ( DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n"));=0D }=0D =0D + //=0D + // Parse memory info and build memory HOBs for reserved DRAM and MMIO=0D + //=0D + Status =3D ParseMemoryInfo (MemInfoCallbackMMIO, &AcpiBoardInfo);=0D + if (EFI_ERROR(Status)) {=0D + return Status;=0D + }=0D +=0D //=0D // Parse platform specific information.=0D //=0D diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h b/UefiPaylo= adPkg/UefiPayloadEntry/UefiPayloadEntry.h index 2c84d6ed53..35ea23d202 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h +++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h @@ -38,6 +38,16 @@ #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \=0D ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((= Alignment) - 1)))=0D =0D +=0D +#define E820_RAM 1=0D +#define E820_RESERVED 2=0D +#define E820_ACPI 3=0D +#define E820_NVS 4=0D +#define E820_UNUSABLE 5=0D +#define E820_DISABLED 6=0D +#define E820_PMEM 7=0D +#define E820_UNDEFINED 8=0D +=0D /**=0D Auto-generated function that calls the library constructors for all of t= he module's=0D dependent libraries.=0D --=20 2.30.2