From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by mx.groups.io with SMTP id smtpd.web12.5533.1623108884432357686 for ; Mon, 07 Jun 2021 16:34:45 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=R5CETWQ5; spf=pass (domain: nuviainc.com, ip: 209.85.128.48, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f48.google.com with SMTP id s70-20020a1ca9490000b02901a589651424so698361wme.0 for ; Mon, 07 Jun 2021 16:34:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=LLNyeAHaWQ0dXWHsoVKFmBBoc4omDAyF2dBxbk76nqg=; b=R5CETWQ5OGVir6UwzyPm3zH6KTwzeIy6iTn48BdoF37SsRCDG8z2ctLKpuWkFCLu1U njUK57jml3iGGBzL3K05/aIEtfhwnwjWbZ5JlN+4SlsM7kswlOZfR0c+31bV63RNRqgW bGBW9PSQJBVCkwpnjnjlcXFFbvABWINsCfjzla/WpcUAG78ezLXHpwfzCuwzqZotiFMA CiEslg+mCglxj9DYGl8rVN/muVvFQLHMKET7gro/b92tI/XnvFCkesT+IkA//Ol+BJde TzDnzziMFIKQ5NF5ueF4+HOjGeHYDE62hZdhLyUGUKovgdQbndC18GpeEJtKwN8I68oR jVTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=LLNyeAHaWQ0dXWHsoVKFmBBoc4omDAyF2dBxbk76nqg=; b=d9Vb2bWddchfJgTsKw76Z/U4Kj2xvYpuuVMdrRessK0ZzhFHd+wniN3ekfeT7cI1YE C4+WnaeQHnK+aHjXxx8XtSABMx61KIYpfrGkZ9HuEbq7VfXW31AYaslZGnaP0b4uY2f+ WQsiUb/UojNf31YnKkBN7AhzYzELESwfxigKNOat8qrycKmQYaMyxMC/IWurVQLRV4SE 5V0/b1R94ECOB1Au7yc/TJkGpADXIeq4xzYYfEASoL0ECVmgd96d/xwXVmSxs2EYkeSV 6YjzxTwrXJ+QcF8SLQ4MsCz59BnVCBtLA8Yutxk+sOcof+OqC8Oir32py1ufVTnkyE7Q 6ZCA== X-Gm-Message-State: AOAM530TtrKhbY5571yNUy2arpbJV3EfNxYOhFIH2DWcSL3mEGJE3Fdz aCFy6t3HmgUup8cdPJNI9bt5JQ== X-Google-Smtp-Source: ABdhPJwNtx6cBzZdYpv157Hw1SLwKTI2NFfifT8FulMwHLBaL6JFG+XFVPiPkhRCdMMRXu52OLM9/Q== X-Received: by 2002:a05:600c:3b13:: with SMTP id m19mr19193948wms.53.1623108882709; Mon, 07 Jun 2021 16:34:42 -0700 (PDT) Return-Path: Received: from leviathan (cpc1-cmbg19-2-0-cust915.5-4.cable.virginm.net. [82.27.183.148]) by smtp.gmail.com with ESMTPSA id 32sm19572847wrs.5.2021.06.07.16.34.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Jun 2021 16:34:42 -0700 (PDT) Date: Tue, 8 Jun 2021 00:34:40 +0100 From: "Leif Lindholm" To: Nhi Pham Cc: devel@edk2.groups.io, Vu Nguyen , Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: Re: [edk2-platforms][PATCH v2 28/32] AmpereAltraPkg: Add configuration screen for Pcie Devices Message-ID: <20210607233440.kidc5izx7wajwpyi@leviathan> References: <20210526100724.5359-1-nhi@os.amperecomputing.com> <20210526100724.5359-30-nhi@os.amperecomputing.com> MIME-Version: 1.0 In-Reply-To: <20210526100724.5359-30-nhi@os.amperecomputing.com> Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On Wed, May 26, 2021 at 17:07:20 +0700, Nhi Pham wrote: > From: Vu Nguyen > > This screen provide menu options to configure Max Payload and Max Read > Request size for each PCIe device under Root Port. PCIe devices which > attach to external switch are not supported yet. > > Cc: Thang Nguyen > Cc: Chuong Tran > Cc: Phong Vo > Cc: Leif Lindholm > Cc: Michael D Kinney > Cc: Ard Biesheuvel > Cc: Nate DeSimone > > Signed-off-by: Vu Nguyen > --- > Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 3 + > Platform/Ampere/JadePkg/Jade.dsc | 1 + > Platform/Ampere/JadePkg/Jade.fdf | 1 + > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.inf | 59 ++ > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/NVDataStruc.h | 56 ++ > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.h | 78 ++ > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.h | 58 ++ > Silicon/Ampere/AmpereAltraPkg/Include/Guid/PcieDeviceConfigHii.h | 19 + > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/Vfr.vfr | 50 + > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.c | 1046 ++++++++++++++++++++ > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.c | 191 ++++ > Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.uni | 24 + > 12 files changed, 1586 insertions(+) > > diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > index 53930869f4f6..62e27c8b49b2 100644 > --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > @@ -59,6 +59,9 @@ [Guids] > # GUID for the Watchdog HII configuration form > gWatchdogConfigFormSetGuid = { 0xC3F8EC6E, 0x95EE, 0x460C, { 0xA4, 0x8D, 0xEA, 0x54, 0x2F, 0xFF, 0x01, 0x61 } } > > + # GUID for the Pcie Device HII configuration form > + gPcieDeviceConfigFormSetGuid = { 0xEC7B1D21, 0x9167, 0x4B9D, { 0xF7, 0x94, 0xCD, 0x1A, 0xEB, 0xBC, 0xB7, 0x59 } } > + > ## NVParam MM GUID > gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } } > > diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc > index 391ff75e237c..9d787113e3b5 100755 > --- a/Platform/Ampere/JadePkg/Jade.dsc > +++ b/Platform/Ampere/JadePkg/Jade.dsc > @@ -184,3 +184,4 @@ [Components.common] > Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf > Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf > Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf > + Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.inf > diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf > index 431c9906e98e..b0c2894d00f8 100755 > --- a/Platform/Ampere/JadePkg/Jade.fdf > +++ b/Platform/Ampere/JadePkg/Jade.fdf > @@ -359,5 +359,6 @@ [FV.FvMain] > INF Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf > INF Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf > INF Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf > + INF Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.inf > > !include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.inf > new file mode 100644 > index 000000000000..a04c79661842 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.inf > @@ -0,0 +1,59 @@ > +## @file > +# > +# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = PcieDeviceConfigDxe > + FILE_GUID = 17E9369D-0A1B-45F4-A286-B1DED6D85D33 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = PcieDeviceConfigEntryPoint > + > +[Sources.common] > + NVDataStruc.h > + PcieDeviceConfigDxe.c > + PcieDeviceConfigDxe.h > + PcieDeviceConfigDxe.uni > + PcieHelper.c > + PcieHelper.h > + Vfr.vfr > + > +[Packages] > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > + Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + DevicePathLib > + HiiLib > + MemoryAllocationLib > + PrintLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiLib > + UefiRuntimeServicesTableLib > + > +[Protocols] > + gEfiPciIoProtocolGuid > + gEfiDevicePathProtocolGuid ## CONSUMES > + gEfiHiiConfigRoutingProtocolGuid ## CONSUMES > + gEfiHiiConfigAccessProtocolGuid ## PRODUCES > + gEfiDevicePathToTextProtocolGuid > + > +[Guids] > + gEfiIfrTianoGuid > + gPcieDeviceConfigFormSetGuid > + gPlatformManagerFormsetGuid > + gPlatformManagerEntryEventGuid > + > +[Depex] > + TRUE > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/NVDataStruc.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/NVDataStruc.h > new file mode 100644 > index 000000000000..fb168e495670 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/NVDataStruc.h > @@ -0,0 +1,56 @@ > +/** @file > + > + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef NVDATASTRUC_H_ > +#define NVDATASTRUC_H_ > + > +#include > + > +#define VARSTORE_NAME L"PcieDeviceConfigNVData" > + > +#define MAIN_FORM_ID 0x01 > +#define DEVICE_FORM_ID 0x02 > +#define VARSTORE_ID 0x03 > + > +#define MAIN_LABEL_UPDATE 0x21 > +#define MAIN_LABEL_END 0x22 > +#define DEVICE_LABEL_UPDATE 0x31 > +#define DEVICE_LABEL_END 0x32 > + > +#define DEVICE_KEY 0x6000 > +#define MPS_ONE_OF_KEY 0x7000 > +#define MRR_ONE_OF_KEY 0x8000 > + > +#define MAX_DEVICE 40 > + > +#define DEFAULT_MPS 0x00 // Section 7.5.3.4 > +#define DEFAULT_MRR 0x02 // Section 7.5.3.4 > + > +#define PCIE_ADD(Vid, Did, Seg, Bus, Dev) \ > + (UINT64)(Vid) << 40 | (UINT64)(Did) << 24 | Seg << 16 | Bus << 8 | Dev; > + > +#pragma pack(1) > + > +typedef struct { > + UINT8 DEV; > + UINT8 BUS; > + UINT8 SEG; > + UINT16 DID; > + UINT16 VID; > + UINT8 SlotId; > +} SLOT_INFO; > + > +typedef struct { > + UINT8 MPS[MAX_DEVICE]; > + UINT8 MRR[MAX_DEVICE]; > + UINT64 SlotInfo[MAX_DEVICE]; > +} VARSTORE_DATA; > + > +#pragma pack() > + > +#endif // NVDATASTRUC_H_ > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.h > new file mode 100644 > index 000000000000..40d7da1ef277 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.h > @@ -0,0 +1,78 @@ > +/** @file > + > + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef PCIE_DEVICE_CONFIG_H_ > +#define PCIE_DEVICE_CONFIG_H_ Again, concern with claiming part of global PCIE namespace. > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "NVDataStruc.h" > + > +#define MAX_STRING_SIZE 100 > + > +#define PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'E', 'D', 'C') > +#define PRIVATE_DATA_FROM_THIS(a) \ > + CR (a, PRIVATE_DATA, ConfigAccess, PRIVATE_DATA_SIGNATURE) > + > +#pragma pack(1) > + > +/// > +/// HII specific Vendor Device Path definition. > +/// > +typedef struct { > + VENDOR_DEVICE_PATH VendorDevicePath; > + EFI_DEVICE_PATH_PROTOCOL End; > +} HII_VENDOR_DEVICE_PATH; > + > +#pragma pack() > + > +// > +// This is the generated IFR binary data for each formset defined in VFR. > +// This data array is ready to be used as input of HiiAddPackages() to > +// create a packagelist (which contains Form packages, String packages, etc). > +// > +extern UINT8 VfrBin[]; PlatformPcieDeviceConfigVfrBin? > + > +// > +// This is the generated String package data for all .UNI files. > +// This data array is ready to be used as input of HiiAddPackages() to > +// create a packagelist (which contains Form packages, String packages, etc). > +// > +extern UINT8 PcieDeviceConfigDxeStrings[]; > + > +typedef struct { > + UINTN Signature; > + > + EFI_HANDLE DriverHandle; > + EFI_HII_HANDLE HiiHandle; > + VARSTORE_DATA LastVarStoreConfig; > + VARSTORE_DATA VarStoreConfig; > + > + // > + // Consumed protocol > + // > + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; > + EFI_HII_STRING_PROTOCOL *HiiString; > + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; > + EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler; > + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; > + > + // > + // Produced protocol > + // > + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; > +} PRIVATE_DATA; > + > +#endif // PCIE_DEVICE_CONFIG_H_ > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.h > new file mode 100644 > index 000000000000..32787865119d > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.h > @@ -0,0 +1,58 @@ > +/** @file > + > + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef PCIE_HELPER_H_ > +#define PCIE_HELPER_H_ > + > +#define PCIE_MAX_PAYLOAD_MASK 0x07 > +#define PCIE_CONTROL_MAX_PAYLOAD_OFF 5 > +#define PCIE_MAX_READ_REQUEST_MASK 0x07 > +#define PCIE_CONTROL_READ_REQUEST_OFF 12 > + > +#define PCI_EXPRESS_CAPABILITY_DEVICE_CAPABILITIES_REG 0x04 > +#define PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG 0x08 > + > +#define FOR_EACH(Node, Tail, Type) \ > + for (Node = Tail->Type; Node != NULL; Node = Node->Type) > + > +struct _PCIE_NODE { > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT8 MaxMps; > + UINT8 PcieCapOffset; > + UINT16 Vid; > + UINT16 Did; > + UINT8 Seg; > + UINT8 Bus; > + UINT8 Dev; > + UINT8 Fun; > + struct _PCIE_NODE *Parent; > + struct _PCIE_NODE *Brother; > +}; > + > +typedef struct _PCIE_NODE PCIE_NODE; > + > +EFI_STATUS > +WriteMps ( > + PCIE_NODE *Node, > + UINT8 Value > + ); > + > +EFI_STATUS > +WriteMrr ( > + PCIE_NODE *Node, > + UINT8 Value > + ); > + > +EFI_STATUS > +FindCapabilityPtr ( > + IN EFI_PCI_IO_PROTOCOL *PciIo, > + IN UINT8 CapabilityId, > + OUT UINT8 *CapabilityPtr > + ); > + > +#endif // PCIE_HELPER_H_ > diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Guid/PcieDeviceConfigHii.h b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/PcieDeviceConfigHii.h > new file mode 100644 > index 000000000000..04b950abd49e > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/PcieDeviceConfigHii.h > @@ -0,0 +1,19 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef PCIE_DEVICE_CONFIG_HII_H_ > +#define PCIE_DEVICE_CONFIG_HII_H_ > + > +#define PCIE_DEVICE_CONFIG_FORMSET_GUID \ > + { \ > + 0xEC7B1D21, 0x9167, 0x4B9D, { 0xF7, 0x94, 0xCD, 0x1A, 0xEB, 0xBC, 0xB7, 0x59 } \ > + } > + > +extern EFI_GUID gPcieDeviceConfigFormSetGuid; > + > +#endif /* PCIE_DEVICE_CONFIG_HII_H_ */ > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/Vfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/Vfr.vfr > new file mode 100644 > index 000000000000..b5b16802b23e > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/Vfr.vfr > @@ -0,0 +1,50 @@ > +/** @file > + > + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include "NVDataStruc.h" > + > +formset > + guid = PCIE_DEVICE_CONFIG_FORMSET_GUID, > + title = STRING_TOKEN(STR_PCIE_DEVICE_CONFIG_FORM), > + help = STRING_TOKEN(STR_PCIE_DEVICE_CONFIG_HELP), > + classguid = gPlatformManagerFormsetGuid, > + > + // > + // Define a variable Storage > + // > + varstore VARSTORE_DATA, > + varid = VARSTORE_ID, > + name = PcieDeviceConfigNVData, > + guid = PCIE_DEVICE_CONFIG_FORMSET_GUID; > + > + form > + formid = MAIN_FORM_ID, > + title = STRING_TOKEN(STR_PCIE_DEVICE_CONFIG_FORM); > + > + subtitle text = STRING_TOKEN(STR_PCIE_DEVICE_CONFIG_FORM); > + > + label MAIN_LABEL_UPDATE; > + // dynamic content here > + label MAIN_LABEL_END; > + > + endform; > + > + form > + formid = DEVICE_FORM_ID, > + title = STRING_TOKEN(STR_DEVICE_FORM); > + > + subtitle text = STRING_TOKEN(STR_DEVICE_FORM); > + > + label DEVICE_LABEL_UPDATE; > + // dynamic content here > + label DEVICE_LABEL_END; > + > + endform; > + > +endformset; > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.c > new file mode 100644 > index 000000000000..a04f789530c0 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.c > @@ -0,0 +1,1046 @@ > +/** @file > + > + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "PcieDeviceConfigDxe.h" > +#include "PcieHelper.h" > + > +VOID *mPciProtocolNotifyRegistration; > +CHAR16 *mVariableName = VARSTORE_NAME; > +PCIE_NODE *mDeviceBuf[MAX_DEVICE] = {NULL}; > + > +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { > + { > + { > + HARDWARE_DEVICE_PATH, > + HW_VENDOR_DP, > + { > + (UINT8)(sizeof (VENDOR_DEVICE_PATH)), > + (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8) > + } > + }, > + PCIE_DEVICE_CONFIG_FORMSET_GUID > + }, > + { > + END_DEVICE_PATH_TYPE, > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { > + (UINT8)(END_DEVICE_PATH_LENGTH), > + (UINT8)((END_DEVICE_PATH_LENGTH) >> 8) > + } > + } > +}; > + > +VOID > +FlushDeviceData ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + EFI_STATUS Status; > + PCIE_NODE *Node; > + PRIVATE_DATA *PrivateData; > + UINT8 Index; > + VARSTORE_DATA *LastVarStoreConfig; > + VARSTORE_DATA *VarStoreConfig; > + > + PrivateData = (PRIVATE_DATA *)Context; > + LastVarStoreConfig = &PrivateData->LastVarStoreConfig; > + VarStoreConfig = &PrivateData->VarStoreConfig; > + > + // > + // If config has changed, update NVRAM > + // > + if (CompareMem (VarStoreConfig, LastVarStoreConfig, sizeof (VARSTORE_DATA)) != 0) { > + DEBUG ((DEBUG_INFO, "%a Update Device Config Variable\n", __FUNCTION__)); > + Status = gRT->SetVariable ( > + mVariableName, > + &gPcieDeviceConfigFormSetGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, > + sizeof (VARSTORE_DATA), > + VarStoreConfig > + ); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a: Failed to set variable status %r", > + __FUNCTION__, > + Status > + )); > + return; > + } > + } > + > + // Iterate through the list, then write corresponding MPS MRR > + for (Index = 0; Index < MAX_DEVICE; Index++) { > + if (mDeviceBuf[Index] == NULL) { > + continue; > + } > + > + // Write MPS value > + WriteMps (mDeviceBuf[Index], VarStoreConfig->MPS[Index]); > + > + FOR_EACH (Node, mDeviceBuf[Index], Parent) { > + WriteMps (Node, VarStoreConfig->MPS[Index]); > + } > + > + FOR_EACH (Node, mDeviceBuf[Index], Brother) { > + WriteMps (Node, VarStoreConfig->MPS[Index]); > + } > + > + // Write MRR value > + // FIXME: No need to update MRR of parent node Please drop FIXME. > + WriteMrr (mDeviceBuf[Index], VarStoreConfig->MRR[Index]); > + > + FOR_EACH (Node, mDeviceBuf[Index], Brother) { > + WriteMrr (Node, VarStoreConfig->MRR[Index]); > + } > + } > + > + gBS->CloseEvent (Event); > +} > + > +EFI_STATUS > +UpdateDeviceForm ( > + UINT8 Index, > + PRIVATE_DATA *PrivateData > + ) > +{ > + CHAR16 Str[MAX_STRING_SIZE]; > + UINT8 MaxMps; > + > + VOID *StartOpCodeHandle; > + EFI_IFR_GUID_LABEL *StartLabel; > + VOID *EndOpCodeHandle; > + EFI_IFR_GUID_LABEL *EndLabel; > + VOID *MpsOpCodeHandle; > + VOID *MrrOpCodeHandle; > + PCIE_NODE *Node; > + > + if (mDeviceBuf[Index] == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + MaxMps = mDeviceBuf[Index]->MaxMps; > + FOR_EACH (Node, mDeviceBuf[Index], Parent) { > + if (Node->MaxMps < MaxMps) { > + MaxMps = Node->MaxMps; > + } > + } > + > + UnicodeSPrint ( > + Str, > + sizeof (Str), > + L"PCIe Device 0x%04x:0x%04x", > + mDeviceBuf[Index]->Vid, > + mDeviceBuf[Index]->Did > + ); > + > + HiiSetString ( > + PrivateData->HiiHandle, > + STRING_TOKEN (STR_DEVICE_FORM), > + Str, > + NULL > + ); > + > + // > + // Initialize the container for dynamic opcodes > + // > + StartOpCodeHandle = HiiAllocateOpCodeHandle (); > + ASSERT (StartOpCodeHandle != NULL); > + > + EndOpCodeHandle = HiiAllocateOpCodeHandle (); > + ASSERT (EndOpCodeHandle != NULL); > + > + // > + // Create Hii Extend Label OpCode as the start opcode > + // > + StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( > + StartOpCodeHandle, > + &gEfiIfrTianoGuid, > + NULL, > + sizeof (EFI_IFR_GUID_LABEL) > + ); > + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; > + StartLabel->Number = DEVICE_LABEL_UPDATE; > + > + // > + // Create Hii Extend Label OpCode as the end opcode > + // > + EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( > + EndOpCodeHandle, > + &gEfiIfrTianoGuid, > + NULL, > + sizeof (EFI_IFR_GUID_LABEL) > + ); > + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; > + EndLabel->Number = DEVICE_LABEL_END; > + > + // Create Option OpCode for MPS selection > + MpsOpCodeHandle = HiiAllocateOpCodeHandle (); > + ASSERT (MpsOpCodeHandle != NULL); > + > + switch (MaxMps) { > + case 5: > + HiiCreateOneOfOptionOpCode ( > + MpsOpCodeHandle, > + STRING_TOKEN (STR_4096), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 5 > + ); > + > + case 4: > + HiiCreateOneOfOptionOpCode ( > + MpsOpCodeHandle, > + STRING_TOKEN (STR_2048), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 4 > + ); > + > + case 3: > + HiiCreateOneOfOptionOpCode ( > + MpsOpCodeHandle, > + STRING_TOKEN (STR_1024), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 3 > + ); > + > + case 2: > + HiiCreateOneOfOptionOpCode ( > + MpsOpCodeHandle, > + STRING_TOKEN (STR_512), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 2 > + ); > + > + case 1: > + HiiCreateOneOfOptionOpCode ( > + MpsOpCodeHandle, > + STRING_TOKEN (STR_256), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 1 > + ); > + > + case 0: > + HiiCreateOneOfOptionOpCode ( > + MpsOpCodeHandle, > + STRING_TOKEN (STR_128), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 0 > + ); > + } > + > + // Create MPS OneOf > + HiiCreateOneOfOpCode ( > + StartOpCodeHandle, // Container for dynamic created opcodes > + (MPS_ONE_OF_KEY + Index), // Question ID (or call it "key") > + VARSTORE_ID, // VarStore ID > + Index, // Offset in Buffer Storage > + STRING_TOKEN (STR_PCIE_MPS), // Question prompt text > + STRING_TOKEN (STR_PCIE_MPS_HELP), // Question help text > + EFI_IFR_FLAG_CALLBACK, // Question flag > + EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value > + MpsOpCodeHandle, // Option Opcode list > + NULL // Default Opcode is NULl > + ); > + > + // Create Option OpCode for MRR selection > + MrrOpCodeHandle = HiiAllocateOpCodeHandle (); > + ASSERT (MrrOpCodeHandle != NULL); > + > + HiiCreateOneOfOptionOpCode ( > + MrrOpCodeHandle, > + STRING_TOKEN (STR_4096), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 5 > + ); > + > + HiiCreateOneOfOptionOpCode ( > + MrrOpCodeHandle, > + STRING_TOKEN (STR_2048), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 4 > + ); > + > + HiiCreateOneOfOptionOpCode ( > + MrrOpCodeHandle, > + STRING_TOKEN (STR_1024), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 3 > + ); > + > + HiiCreateOneOfOptionOpCode ( > + MrrOpCodeHandle, > + STRING_TOKEN (STR_512), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 2 > + ); > + > + HiiCreateOneOfOptionOpCode ( > + MrrOpCodeHandle, > + STRING_TOKEN (STR_256), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 1 > + ); > + > + HiiCreateOneOfOptionOpCode ( > + MrrOpCodeHandle, > + STRING_TOKEN (STR_128), > + 0, > + EFI_IFR_NUMERIC_SIZE_1, > + 0 > + ); > + > + // Create MRR OneOf > + HiiCreateOneOfOpCode ( > + StartOpCodeHandle, // Container for dynamic created opcodes > + (MRR_ONE_OF_KEY + Index), // Question ID (or call it "key") > + VARSTORE_ID, // VarStore ID > + MAX_DEVICE + Index, // Offset in Buffer Storage > + STRING_TOKEN (STR_PCIE_MRR), // Question prompt text > + STRING_TOKEN (STR_PCIE_MRR_HELP), // Question help text > + EFI_IFR_FLAG_CALLBACK, // Question flag > + EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value > + MrrOpCodeHandle, // Option Opcode list > + NULL // Default Opcode is NULl > + ); > + > + HiiUpdateForm ( > + PrivateData->HiiHandle, // HII handle > + &gPcieDeviceConfigFormSetGuid, // Formset GUID > + DEVICE_FORM_ID, // Form ID > + StartOpCodeHandle, // Label for where to insert opcodes > + EndOpCodeHandle // Insert data > + ); > + > + HiiFreeOpCodeHandle (StartOpCodeHandle); > + HiiFreeOpCodeHandle (EndOpCodeHandle); > + HiiFreeOpCodeHandle (MpsOpCodeHandle); > + HiiFreeOpCodeHandle (MrrOpCodeHandle); > + return EFI_SUCCESS; > +} > + > +VOID > +OnPciIoProtocolNotify ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + EFI_STATUS Status; > + EFI_HANDLE HandleBuffer; > + PCI_TYPE00 Pci; > + > + UINTN BufferSize; > + UINTN PciBusNumber; > + UINTN PciDeviceNumber; > + UINTN PciFunctionNumber; > + UINTN PciSegment; > + > + UINT8 Idx; > + UINT8 CapabilityPtr; > + UINT16 TmpValue; > + UINT64 SlotInfo; > + > + PCIE_NODE *Node; > + PRIVATE_DATA *PrivateData; > + STATIC PCIE_NODE *LastNode; > + STATIC UINT8 Index; > + STATIC UINT8 LastBus; > + > + VARSTORE_DATA *LastVarStoreConfig; > + VARSTORE_DATA *VarStoreConfig; > + > + PrivateData = (PRIVATE_DATA *)Context; > + LastVarStoreConfig = &PrivateData->LastVarStoreConfig; > + VarStoreConfig = &PrivateData->VarStoreConfig; > + > + while (TRUE) { > + BufferSize = sizeof (EFI_HANDLE); > + Status = gBS->LocateHandle ( > + ByRegisterNotify, > + NULL, > + mPciProtocolNotifyRegistration, > + &BufferSize, > + &HandleBuffer > + ); > + if (EFI_ERROR (Status)) { > + break; > + } > + > + Status = gBS->HandleProtocol ( > + HandleBuffer, > + &gEfiPciIoProtocolGuid, > + (VOID **)&PciIo > + ); > + if (EFI_ERROR (Status)) { > + break; > + } > + > + // Get device bus location > + Status = PciIo->GetLocation ( > + PciIo, > + &PciSegment, > + &PciBusNumber, > + &PciDeviceNumber, > + &PciFunctionNumber > + ); > + if (EFI_ERROR (Status) || > + ((PciBusNumber == 0) && (PciDeviceNumber == 0))) > + { > + // Filter out Host Bridge > + DEBUG ((DEBUG_INFO, "Filter out Host Bridge %x\n", PciSegment)); > + continue; > + } > + > + DEBUG (( > + DEBUG_INFO, > + ">> Dev 0x%04x:0x%02x:0x%02x:0x%02x\n", > + PciSegment, > + PciBusNumber, > + PciDeviceNumber, > + PciFunctionNumber > + )); > + > + Status = FindCapabilityPtr (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &CapabilityPtr); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a: PCI Express Capability not found\n", > + __FUNCTION__ > + )); > + continue; > + } > + > + // Get Device's max MPS support > + Status = PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + CapabilityPtr + PCI_EXPRESS_CAPABILITY_DEVICE_CAPABILITIES_REG, > + 1, > + &TmpValue > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + // Read device's VID:PID > + Status = PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint32, > + 0, > + sizeof (Pci) / sizeof (UINT32), > + &Pci > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + DEBUG (( > + DEBUG_INFO, > + "VendorId 0x%04x - DeviceId 0x%04x\n", > + Pci.Hdr.VendorId, > + Pci.Hdr.DeviceId > + )); > + > + Node = AllocateZeroPool (sizeof (*Node)); > + Node->MaxMps = TmpValue & PCIE_MAX_PAYLOAD_MASK; > + Node->PcieCapOffset = CapabilityPtr; > + Node->PciIo = PciIo; > + Node->Seg = PciSegment; > + Node->Bus = PciBusNumber; > + Node->Dev = PciDeviceNumber; > + Node->Fun = PciFunctionNumber; > + Node->Vid = Pci.Hdr.VendorId; > + Node->Did = Pci.Hdr.DeviceId; > + SlotInfo = PCIE_ADD (Node->Vid, Node->Did, Node->Seg, Node->Bus, Node->Dev); > + > + // Presume child devices were registered follow root port > + if (PciBusNumber != 0) { > + if (LastBus == 0) { > + Node->Parent = LastNode; > + mDeviceBuf[Index] = Node; > + > + VarStoreConfig->MPS[Index] = DEFAULT_MPS; > + VarStoreConfig->MRR[Index] = DEFAULT_MRR; > + VarStoreConfig->SlotInfo[Index] = SlotInfo; > + > + // Retrieve setting from previous variable > + for (Idx = 0; Idx < MAX_DEVICE; Idx++) { > + if (SlotInfo == LastVarStoreConfig->SlotInfo[Idx]) { > + VarStoreConfig->MPS[Index] = LastVarStoreConfig->MPS[Idx]; > + VarStoreConfig->MRR[Index] = LastVarStoreConfig->MRR[Idx]; > + break; > + } > + } > + > + Index++; > + } else if (PciBusNumber == LastBus) { > + LastNode->Brother = Node; > + } else { > + // Ignore devices don't stay under root port > + continue; > + } > + } > + > + LastBus = PciBusNumber; > + LastNode = Node; > + } > +} > + > +VOID > +UpdateMainForm ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + UINTN Index; > + EFI_STRING_ID StrId; > + CHAR16 Str[MAX_STRING_SIZE]; > + VOID *StartOpCodeHandle; > + EFI_IFR_GUID_LABEL *StartLabel; > + VOID *EndOpCodeHandle; > + EFI_IFR_GUID_LABEL *EndLabel; > + PRIVATE_DATA *PrivateData; > + > + DEBUG ((DEBUG_INFO, "%a Entry ...\n", __FUNCTION__)); > + > + PrivateData = (PRIVATE_DATA *)Context; > + > + // > + // Initialize the container for dynamic opcodes > + // > + StartOpCodeHandle = HiiAllocateOpCodeHandle (); > + ASSERT (StartOpCodeHandle != NULL); > + > + EndOpCodeHandle = HiiAllocateOpCodeHandle (); > + ASSERT (EndOpCodeHandle != NULL); > + > + // > + // Create Hii Extend Label OpCode as the start opcode > + // > + StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( > + StartOpCodeHandle, > + &gEfiIfrTianoGuid, > + NULL, > + sizeof (EFI_IFR_GUID_LABEL) > + ); > + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; > + StartLabel->Number = MAIN_LABEL_UPDATE; > + > + // > + // Create Hii Extend Label OpCode as the end opcode > + // > + EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( > + EndOpCodeHandle, > + &gEfiIfrTianoGuid, > + NULL, > + sizeof (EFI_IFR_GUID_LABEL) > + ); > + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; > + EndLabel->Number = MAIN_LABEL_END; > + > + for (Index = 0; Index < MAX_DEVICE; Index++) { > + if (mDeviceBuf[Index] == NULL) { > + break; > + } > + DEBUG ((DEBUG_INFO, ">> Add item %d\n", Index)); > + > + // TODO: convert and store in SlotID ex:SystemSlot(seg, bus, dev) Please drop TODO. > + UnicodeSPrint ( > + Str, > + sizeof (Str), > + L"PCIe Device 0x%04x:0x%04x - %04x:%02x:%02x", > + mDeviceBuf[Index]->Vid, > + mDeviceBuf[Index]->Did, > + mDeviceBuf[Index]->Seg, > + mDeviceBuf[Index]->Bus, > + mDeviceBuf[Index]->Dev > + ); > + > + StrId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL); > + > + // > + // Create a Goto OpCode to device configuration > + // > + HiiCreateGotoOpCode ( > + StartOpCodeHandle, // Container for dynamic created opcodes > + DEVICE_FORM_ID, // Target Form ID > + StrId, // Prompt text > + STRING_TOKEN (STR_DEVICE_GOTO_HELP), // Help text > + EFI_IFR_FLAG_CALLBACK, // Question flag > + (DEVICE_KEY + Index) // Question ID > + ); > + } > + > + HiiUpdateForm ( > + PrivateData->HiiHandle, // HII handle > + &gPcieDeviceConfigFormSetGuid, // Formset GUID > + MAIN_FORM_ID, // Form ID > + StartOpCodeHandle, // Label for where to insert opcodes > + EndOpCodeHandle // Insert data > + ); > + > + HiiFreeOpCodeHandle (StartOpCodeHandle); > + HiiFreeOpCodeHandle (EndOpCodeHandle); > + > + gBS->CloseEvent (Event); > +} > + > +EFI_STATUS > +EFIAPI > +ExtractConfig ( > + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, > + IN CONST EFI_STRING Request, > + OUT EFI_STRING *Progress, > + OUT EFI_STRING *Results > + ) > +{ > + EFI_STATUS Status; > + UINTN BufferSize; > + PRIVATE_DATA *PrivateData; > + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; > + EFI_STRING ConfigRequest; > + EFI_STRING ConfigRequestHdr; > + UINTN Size; > + CHAR16 *StrPointer; > + BOOLEAN AllocatedRequest; > + VARSTORE_DATA *VarStoreConfig; > + > + if (Progress == NULL || Results == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + // > + // Initialize the local variables. > + // > + ConfigRequestHdr = NULL; > + ConfigRequest = NULL; > + Size = 0; > + *Progress = Request; > + AllocatedRequest = FALSE; > + > + PrivateData = PRIVATE_DATA_FROM_THIS (This); > + HiiConfigRouting = PrivateData->HiiConfigRouting; > + VarStoreConfig = &PrivateData->VarStoreConfig; > + ASSERT (VarStoreConfig != NULL); > + > + BufferSize = sizeof (VARSTORE_DATA); > + > + if (Request == NULL) { > + // > + // Request is set to NULL, construct full request string. > + // > + > + // > + // Allocate and fill a buffer large enough to hold the template > + // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a > + // Null-terminator > + // > + ConfigRequestHdr = HiiConstructConfigHdr ( > + &gPcieDeviceConfigFormSetGuid, > + mVariableName, > + PrivateData->DriverHandle > + ); > + if (ConfigRequestHdr == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); > + ConfigRequest = AllocateZeroPool (Size); > + ASSERT (ConfigRequest != NULL); > + AllocatedRequest = TRUE; > + UnicodeSPrint ( > + ConfigRequest, > + Size, > + L"%s&OFFSET=0&WIDTH=%016LX", > + ConfigRequestHdr, > + (UINT64)BufferSize > + ); > + FreePool (ConfigRequestHdr); > + ConfigRequestHdr = NULL; > + } else { > + // > + // Check routing data in . > + // Note: if only one Storage is used, then this checking could be skipped. > + // > + if (!HiiIsConfigHdrMatch (Request, &gPcieDeviceConfigFormSetGuid, NULL)) { > + return EFI_NOT_FOUND; > + } > + // > + // Set Request to the unified request string. > + // > + ConfigRequest = Request; > + > + // > + // Check whether Request includes Request Element. > + // > + if (StrStr (Request, L"OFFSET") == NULL) { > + // > + // Check Request Element does exist in Request String > + // > + StrPointer = StrStr (Request, L"PATH"); > + if (StrPointer == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + if (StrStr (StrPointer, L"&") == NULL) { > + Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16); > + ConfigRequest = AllocateZeroPool (Size); > + ASSERT (ConfigRequest != NULL); > + AllocatedRequest = TRUE; > + UnicodeSPrint ( > + ConfigRequest, > + Size, > + L"%s&OFFSET=0&WIDTH=%016LX", > + Request, > + (UINT64)BufferSize > + ); > + } > + } > + } > + // > + // Check if requesting Name/Value storage > + // > + if (StrStr (ConfigRequest, L"OFFSET") == NULL) { > + // > + // Don't have any Name/Value storage names > + // > + Status = EFI_SUCCESS; > + } else { > + // > + // Convert buffer data to by helper function BlockToConfig() > + // > + Status = HiiConfigRouting->BlockToConfig ( > + HiiConfigRouting, > + ConfigRequest, > + (UINT8 *)VarStoreConfig, > + BufferSize, > + Results, > + Progress > + ); > + } > + // > + // Free the allocated config request string. > + // > + if (AllocatedRequest) { > + FreePool (ConfigRequest); > + } > + if (ConfigRequestHdr != NULL) { > + FreePool (ConfigRequestHdr); > + } > + // > + // Set Progress string to the original request string. > + // > + if (Request == NULL) { > + *Progress = NULL; > + } else if (StrStr (Request, L"OFFSET") == NULL) { > + *Progress = Request + StrLen (Request); > + } > + return Status; > +} > + > +/** > + This function processes the results of changes in configuration. > + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. > + @param Configuration A null-terminated Unicode string in > + format. > + @param Progress A pointer to a string filled in with the offset of > + the most recent '&' before the first failing > + name/value pair (or the beginning of the string if > + the failure is in the first name/value pair) or > + the terminating NULL if all was successful. > + @retval EFI_SUCCESS The Results is processed successfully. > + @retval EFI_INVALID_PARAMETER Configuration is NULL. > + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this > + driver. > +**/ > +EFI_STATUS > +EFIAPI > +RouteConfig ( > + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, > + IN CONST EFI_STRING Configuration, > + OUT EFI_STRING *Progress > + ) > +{ > + EFI_STATUS Status; > + UINTN BufferSize; > + PRIVATE_DATA *PrivateData; > + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; > + VARSTORE_DATA *VarStoreConfig; > + > + if (Configuration == NULL || Progress == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + PrivateData = PRIVATE_DATA_FROM_THIS (This); > + HiiConfigRouting = PrivateData->HiiConfigRouting; > + *Progress = Configuration; > + VarStoreConfig = &PrivateData->VarStoreConfig; > + ASSERT (VarStoreConfig != NULL); > + > + // > + // Check routing data in . > + // Note: if only one Storage is used, then this checking could be skipped. > + // > + if (!HiiIsConfigHdrMatch ( > + Configuration, > + &gPcieDeviceConfigFormSetGuid, > + NULL > + )) > + { > + return EFI_NOT_FOUND; > + } > + > + // > + // Check if configuring Name/Value storage > + // > + if (StrStr (Configuration, L"OFFSET") == NULL) { > + // > + // Don't have any Name/Value storage names > + // > + return EFI_SUCCESS; > + } > + // > + // Convert to buffer data by helper function ConfigToBlock() > + // > + BufferSize = sizeof (VARSTORE_DATA); > + Status = HiiConfigRouting->ConfigToBlock ( > + HiiConfigRouting, > + Configuration, > + (UINT8 *)VarStoreConfig, > + &BufferSize, > + Progress > + ); > + > + return Status; > +} > + > +/** > + This function processes the results of changes in configuration. > + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. > + @param Action Specifies the type of action taken by the browser. > + @param QuestionId A unique value which is sent to the original > + exporting driver so that it can identify the type > + of data to expect. > + @param Type The type of value for the question. > + @param Value A pointer to the data being sent to the original > + exporting driver. > + @param ActionRequest On return, points to the action requested by the > + callback function. > + @retval EFI_SUCCESS The callback successfully handled the action. > + @retval EFI_INVALID_PARAMETER Configuration is NULL. > + @retval EFI_UNSUPPORTED The specified Action is not supported by the > + callback. > +**/ > +EFI_STATUS > +EFIAPI > +DriverCallback ( > + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, > + IN EFI_BROWSER_ACTION Action, > + IN EFI_QUESTION_ID QuestionId, > + IN UINT8 Type, > + IN EFI_IFR_TYPE_VALUE *Value, > + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest > + ) > +{ > + EFI_STATUS Status; > + PRIVATE_DATA *PrivateData; > + > + if (((Value == NULL) && > + (Action != EFI_BROWSER_ACTION_FORM_OPEN) && > + (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) || > + (ActionRequest == NULL)) > + { { on preceding line. > + return EFI_INVALID_PARAMETER; > + } > + > + PrivateData = PRIVATE_DATA_FROM_THIS (This); > + > + switch (Action) { > + case EFI_BROWSER_ACTION_CHANGING: > + if ((QuestionId >= DEVICE_KEY) > + & (QuestionId <= (DEVICE_KEY + MAX_DEVICE))) > + { { on preceding line. More instances below - please fix throughout. / Leif > + Status = UpdateDeviceForm (QuestionId - DEVICE_KEY, PrivateData); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + break; > + > + case EFI_BROWSER_ACTION_DEFAULT_STANDARD: > + case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING: > + if ((QuestionId >= MPS_ONE_OF_KEY) > + & (QuestionId <= (MPS_ONE_OF_KEY + MAX_DEVICE))) > + { > + Value->u8 = DEFAULT_MPS; > + } > + > + if ((QuestionId >= MRR_ONE_OF_KEY) > + & (QuestionId <= (MRR_ONE_OF_KEY + MAX_DEVICE))) > + { > + Value->u8 = DEFAULT_MRR; > + } > + break; > + > + case EFI_BROWSER_ACTION_SUBMITTED: > + break; > + } > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +PcieDeviceConfigEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_HANDLE DriverHandle; > + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; > + EFI_HII_HANDLE HiiHandle; > + EFI_STATUS Status; > + EFI_EVENT PlatformUiEntryEvent; > + EFI_EVENT FlushDeviceEvent; > + EFI_EVENT PciProtocolNotifyEvent; > + PRIVATE_DATA *PrivateData; > + UINTN BufferSize; > + > + DriverHandle = NULL; > + PrivateData = AllocateZeroPool (sizeof (*PrivateData)); > + if (PrivateData == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + PrivateData->Signature = PRIVATE_DATA_SIGNATURE; > + > + PrivateData->ConfigAccess.ExtractConfig = ExtractConfig; > + PrivateData->ConfigAccess.RouteConfig = RouteConfig; > + PrivateData->ConfigAccess.Callback = DriverCallback; > + > + // > + // Locate ConfigRouting protocol > + // > + Status = gBS->LocateProtocol ( > + &gEfiHiiConfigRoutingProtocolGuid, > + NULL, > + (VOID **)&HiiConfigRouting > + ); > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + PrivateData->HiiConfigRouting = HiiConfigRouting; > + > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &DriverHandle, > + &gEfiDevicePathProtocolGuid, > + &mHiiVendorDevicePath, > + &gEfiHiiConfigAccessProtocolGuid, > + &PrivateData->ConfigAccess, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + PrivateData->DriverHandle = DriverHandle; > + > + // > + // Publish our HII data > + // > + HiiHandle = HiiAddPackages ( > + &gPcieDeviceConfigFormSetGuid, > + DriverHandle, > + PcieDeviceConfigDxeStrings, > + VfrBin, > + NULL > + ); > + if (HiiHandle == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto Exit; > + } > + PrivateData->HiiHandle = HiiHandle; > + > + // Event to fixup screen > + Status = gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_CALLBACK, > + UpdateMainForm, > + (VOID *)PrivateData, > + &gPlatformManagerEntryEventGuid, > + &PlatformUiEntryEvent > + ); > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + // Event to collect PciIo > + PciProtocolNotifyEvent = EfiCreateProtocolNotifyEvent ( > + &gEfiPciIoProtocolGuid, > + TPL_CALLBACK, > + OnPciIoProtocolNotify, > + (VOID *)PrivateData, > + &mPciProtocolNotifyRegistration > + ); > + ASSERT (PciProtocolNotifyEvent != NULL); > + > + // Event to flush device data > + Status = gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_CALLBACK, > + FlushDeviceData, > + (VOID *)PrivateData, > + &gEfiEventReadyToBootGuid, > + &FlushDeviceEvent > + ); > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + // Verify varstore > + BufferSize = sizeof (VARSTORE_DATA); > + Status = gRT->GetVariable ( > + mVariableName, > + &gPcieDeviceConfigFormSetGuid, > + NULL, > + &BufferSize, > + &PrivateData->LastVarStoreConfig > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Last config is not found\n", __FUNCTION__)); > + } > + > + return EFI_SUCCESS; > + > +Exit: > + FreePool (PrivateData); > + return Status; > +} > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.c > new file mode 100644 > index 000000000000..b4e918e2b786 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieHelper.c > @@ -0,0 +1,191 @@ > +/** @file > + > + Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > + > +#include "PcieDeviceConfigDxe.h" > +#include "PcieHelper.h" > + > +EFI_STATUS > +FindCapabilityPtr ( > + IN EFI_PCI_IO_PROTOCOL *PciIo, > + IN UINT8 CapabilityId, > + OUT UINT8 *CapabilityPtr > + ) > +{ > + EFI_STATUS Status; > + UINT8 NextPtr; > + UINT16 TmpValue; > + > + ASSERT (PciIo != NULL); > + > + // > + // Get pointer to first PCI Capability header > + // > + Status = PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint8, > + PCI_CAPBILITY_POINTER_OFFSET, > + 1, > + &NextPtr > + ); > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + while (TRUE) { > + if (NextPtr == 0x00) { > + Status = EFI_NOT_FOUND; > + goto Exit; > + } > + > + // > + // Retrieve PCI Capability header > + // > + Status = PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + NextPtr, > + 1, > + &TmpValue > + ); > + if (EFI_ERROR (Status)) { > + goto Exit; > + } > + > + if ((TmpValue & 0xFF) == CapabilityId) { > + *CapabilityPtr = NextPtr; > + Status = EFI_SUCCESS; > + goto Exit; > + } > + > + NextPtr = (TmpValue >> 8) & 0xFF; > + } > + > +Exit: > + return Status; > +} > + > +EFI_STATUS > +WriteMps ( > + PCIE_NODE *Node, > + UINT8 Value > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + EFI_STATUS Status; > + UINT16 TmpValue; > + UINT8 PcieCapOffset; > + > + if (Node == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + PciIo = Node->PciIo; > + PcieCapOffset = Node->PcieCapOffset; > + > + // Get current device control reg > + Status = PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG, > + 1, > + &TmpValue > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Update value and write to device > + TmpValue = (TmpValue & ~(PCIE_MAX_PAYLOAD_MASK << PCIE_CONTROL_MAX_PAYLOAD_OFF)) > + | Value << PCIE_CONTROL_MAX_PAYLOAD_OFF; > + Status = PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG, > + 1, > + &TmpValue > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + DEBUG (( > + DEBUG_INFO, > + "%a: Write MPS %d to device 0x%04x:0x%02x:0x%02x:0x%02x\n", > + __FUNCTION__, > + Value, > + Node->Seg, > + Node->Bus, > + Node->Dev, > + Node->Fun > + )); > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +WriteMrr ( > + PCIE_NODE *Node, > + UINT8 Value > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + EFI_STATUS Status; > + UINT16 TmpValue; > + UINT8 PcieCapOffset; > + > + if (Node == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + PciIo = Node->PciIo; > + PcieCapOffset = Node->PcieCapOffset; > + > + // Get current device control reg > + Status = PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG, > + 1, > + &TmpValue > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Update value and write to device > + TmpValue = (TmpValue & ~(PCIE_MAX_READ_REQUEST_MASK << PCIE_CONTROL_READ_REQUEST_OFF)) > + | Value << PCIE_CONTROL_READ_REQUEST_OFF; > + Status = PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG, > + 1, > + &TmpValue > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + DEBUG (( > + DEBUG_INFO, > + "%a: Write MRR %d to device 0x%04x:0x%02x:0x%02x:0x%02x\n", > + __FUNCTION__, > + Value, > + Node->Seg, > + Node->Bus, > + Node->Dev, > + Node->Fun > + )); > + > + return EFI_SUCCESS; > +} > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.uni > new file mode 100644 > index 000000000000..f07b70c746a6 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PcieDeviceConfigDxe/PcieDeviceConfigDxe.uni > @@ -0,0 +1,24 @@ > +// > +// Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
> +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > + > +#langdef en-US "English" // English > + > +#string STR_PCIE_DEVICE_CONFIG_FORM #language en-US "PCIE Device Configuration" > +#string STR_PCIE_DEVICE_CONFIG_HELP #language en-US "PCIE Device Configuration" > + > +#string STR_DEVICE_FORM #language en-US "PCIE Device Form" > +#string STR_DEVICE_GOTO_HELP #language en-US "PCIE Device Configuration" > + > +#string STR_PCIE_MPS #language en-US "Max Payload Size" > +#string STR_PCIE_MPS_HELP #language en-US "Max Payload Size" > +#string STR_PCIE_MRR #language en-US "Max Read Request Size" > +#string STR_PCIE_MRR_HELP #language en-US "Max Read Request Size" > +#string STR_128 #language en-US "128 bytes" > +#string STR_256 #language en-US "256 bytes" > +#string STR_512 #language en-US "512 bytes" > +#string STR_1024 #language en-US "1024 bytes" > +#string STR_2048 #language en-US "2048 bytes" > +#string STR_4096 #language en-US "4096 bytes" > -- > 2.17.1 >