From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web12.4037.1627524672632945743 for ; Wed, 28 Jul 2021 19:11:12 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=fZMp/hVz; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: nathaniel.l.desimone@intel.com) X-IronPort-AV: E=McAfee;i="6200,9189,10059"; a="209674953" X-IronPort-AV: E=Sophos;i="5.84,276,1620716400"; d="scan'208";a="209674953" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Jul 2021 19:11:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.84,276,1620716400"; d="scan'208";a="634949533" Received: from fmsmsx604.amr.corp.intel.com ([10.18.126.84]) by orsmga005.jf.intel.com with ESMTP; 28 Jul 2021 19:11:08 -0700 Received: from fmsmsx609.amr.corp.intel.com (10.18.126.89) by fmsmsx604.amr.corp.intel.com (10.18.126.84) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2242.10; Wed, 28 Jul 2021 19:11:08 -0700 Received: from fmsmsx605.amr.corp.intel.com (10.18.126.85) by fmsmsx609.amr.corp.intel.com (10.18.126.89) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2242.10; Wed, 28 Jul 2021 19:11:07 -0700 Received: from fmsedg602.ED.cps.intel.com (10.1.192.136) by fmsmsx605.amr.corp.intel.com (10.18.126.85) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2242.4 via Frontend Transport; Wed, 28 Jul 2021 19:11:07 -0700 Received: from NAM02-DM3-obe.outbound.protection.outlook.com (104.47.56.44) by edgegateway.intel.com (192.55.55.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2242.10; Wed, 28 Jul 2021 19:11:06 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=F4apNwNmqGNdIc0/N6NRY/WsQHmR5a9Q52rDKoSCtrJOkYoRLOlgzWITrd9DFK1LpJcY5/hnWqvg1GhzQ6RcdikcBJZRDXlBfnvOS64if3U3ed6cV4VLuXFveGRtvu6qaLcZu3hHK3M6R9XMrZgOmJJZ+07NFfQWKpGL5ifT+sX9VQsFN1ZSn0uWxtfU9r0TUHzdYOTByw8NVkctu41eVng1Mx1IalPxpE5gFmQnNmElZ/ml6K3YanfywwZ6oPXOYkUM9NFWcJ7jzP3OXr1zSJxGWmRa15Xj4udcIDEEDx6ZUpxBhrKtnzXg96rFsKPJzFH0Qq3UbVzRNXx2+QifnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=r1Egam0jpHhCq8a/m9J9xh8OhUVIWLyglwdRHA9pU28=; b=lYh85t4im/jbSiiAHRE+hEdBJ5SoOs7bPNsy7JiW/297E82v90BjW+Mw4T2tPryamUuoJmRRumHecbX1jbMIyx8kMU6XFPztbtmeyN+ri6RSg4rr37O8U/C+LsxcXJ25Xre5q0pbetJe42UX6Rb2udo8XxZdvkobXLyAulXhMw+NQLhZtikCnAG2azgThsML2xgqylTo5aLAtVHknpu5l7PNfJV+tgLxwBsOtqYn+cgDllbJkEhFvfnUbn9DukY727DpPu0ecVdDRs31T4AQS212TlrZ7mU3XnMslSm5+VhRQEUDYyrIFIupMbjyrG9eFjBjFNoySlWe351sEeAvtQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=r1Egam0jpHhCq8a/m9J9xh8OhUVIWLyglwdRHA9pU28=; b=fZMp/hVzTNqbNyT9e6cfeBV8uTuSW+wCZcBLyOTG7rmmHId70gjOTS4qugpWfra7HAxG27EOOGPtrfwbGis5S+VcqLPlZgMA+bSitjXZE+oE3gMN9M/7gR8vLafSY6oPR+Hvq1ZuTPPLikdI/BFGetkaFw38zXzuVlnaE/ZFD8g= Received: from BN6PR1101MB2147.namprd11.prod.outlook.com (2603:10b6:405:57::23) by BN0PR11MB5760.namprd11.prod.outlook.com (2603:10b6:408:169::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4373.21; Thu, 29 Jul 2021 02:10:56 +0000 Received: from BN6PR1101MB2147.namprd11.prod.outlook.com ([fe80::e181:ce91:78af:ee35]) by BN6PR1101MB2147.namprd11.prod.outlook.com ([fe80::e181:ce91:78af:ee35%12]) with mapi id 15.20.4373.020; Thu, 29 Jul 2021 02:10:56 +0000 From: "Nate DeSimone" To: "KARPAGAVINAYAGAM, MANICKAVASAKAM" , "devel@edk2.groups.io" CC: "Oram, Isaac W" , "Felixp@ami.com" , "DOPPALAPUDI, HARIKRISHNA" , "Jha, Manish" , "Bobroff, Zachary" , "KARPAGAVINAYAGAM, MANICKAVASAKAM" Subject: Re: [edk2-platforms] [PATCH V1 2/2] PurleyOpenBoardPkg : Override generic PciBus Driver with Platform specific instance of PciBus driver. Thread-Topic: [edk2-platforms] [PATCH V1 2/2] PurleyOpenBoardPkg : Override generic PciBus Driver with Platform specific instance of PciBus driver. Thread-Index: AQHXYvlJHcxpvdxKQEmD1vRWcTJNLKtZd7Fw Date: Thu, 29 Jul 2021 02:10:56 +0000 Message-ID: References: <20210616214733.10900-1-manickavasakamk@ami.com> In-Reply-To: <20210616214733.10900-1-manickavasakamk@ami.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-reaction: no-action dlp-version: 11.5.1.3 dlp-product: dlpe-windows authentication-results: ami.com; dkim=none (message not signed) header.d=none;ami.com; dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 428eb435-1be9-4783-dfbb-08d9523619f1 x-ms-traffictypediagnostic: BN0PR11MB5760: x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:655; x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 3+SrwY11Z62LfpbJPoyIt79lP9zdg5sTJ3E3jhQJjrkPhG232u8LZ7pywkWjw85BRLB7OwIdilIEIvkkJyT7J1oGV5K+XQJDknx89lagggh8nIYZ6w49PI3naDzamDdhVjtr0hEGmTdu6MW7Gr4jNYod2YFiXkV3yUBbFnHeh0a8PLpQbOQgqwR61a9/bedfVGzTTUjCWU0sN1OCOXRJMK/X/oaUzXTVdOcKvGo6In5SzyIeslGMQELSnn51cXvqgGn5zSlU26YOBvTgC5CNzJq32eJdNxx+gzuh8DtCQaZCRjoE/+zaCamzZmm2bC9gjdM5Hgj+6IYBqcxhgGshb8vfir13GeikwdUz6u/yLqxkooz/7Ayz+6hxOxYq9ZmJ0noWVkP/GmVLBdOfV3ACRQHVpO1pxIhla9CFPfJ19iF95l01AzhK1YDPzlQaq6zS4USoWyOKwZpNTYzOdf2XCkd0sCmQisLGYGl3ssGJjplezsuS8XezwCDrQuiwNgm3rXUywzuOfuOzPmaUN3ys5nehW4nb+o4mO+VBD8qwmkbc7d44/Vi/3AiMa6G3zO8aWb2nIThc/seeEXM1fqOnKc589LCk6DoFMF+qncxP789clrS+m21wDay5JK+35SUu5+FcwZaXYrnrUFK4v0YlfmFFaXOuTtiC9MXZ1Mq4AjD16Ant+aqpw95JyJxnj3aWj9K5RyZasyZulQ8Xf0yWM1HLzEmaU6OIBhgzahvzQsV3zJWKrmMTvYGIqjyXbT40 x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BN6PR1101MB2147.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(346002)(39860400002)(136003)(396003)(376002)(366004)(83380400001)(8676002)(7696005)(54906003)(186003)(110136005)(26005)(5660300002)(52536014)(9686003)(55016002)(33656002)(316002)(30864003)(71200400001)(478600001)(19627235002)(53546011)(6506007)(2906002)(86362001)(66946007)(66476007)(76116006)(66556008)(4326008)(64756008)(66446008)(38100700002)(38070700005)(122000001)(8936002)(41533002)(579004)(569008)(559001)(44824005);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?WSC8DO03qiKeFN9GiLOogmVmpLR8ohpgeyHAX6b0UnfKkkYiF5miHKB/wKEi?= =?us-ascii?Q?lspahzotN6C6Z1cYgUZr5za5RffG5CNomB7aoLMGSaxJ5euLZpzr7LVmDncj?= =?us-ascii?Q?9csnqAQkAxAxHWPuvn9IdTGiW50ruPg0jhMMmp/CG0pu3EecL/319xhqyBqD?= =?us-ascii?Q?Dd3smVpB9tr/SsgWCo4urUfyg8HkotsoRzlu5tRZdfjqNvantgZ3WhwRSI5V?= =?us-ascii?Q?+Ww8lGWVtenFcv8I9gnaO+zg92KgjvBLaaumdgiUphClGjJYl7yFSWHKm7dP?= =?us-ascii?Q?fVlLDZF4FEzq9xJXT7Mu5At97X2mtfBehG7V5IrRg3qzFVsEtRnqa0r0tEQO?= =?us-ascii?Q?Eir6yIHPDFuTwaJS4Q1OSqzn20Ed+y5HLtmeVQkq2NhN2AbdQnlQEbqo4+Kf?= =?us-ascii?Q?jFqTQEkA6xYiRWCSTWZZPPkBdlNmFf3ICcxDlTfCPULhFe3ZFJV1n6tpdKtp?= =?us-ascii?Q?SUjdRuxcCRHDw97tGcdAk5GlG85eBp3ghHdVDgNEsfzB46xnPat9cp0cyLxX?= =?us-ascii?Q?csoincKNJiL17uapTsaRezt9vbYbozgEpVKFcbxn1cysKNyLu/5UJ+sFbVZn?= =?us-ascii?Q?d/G6S+TWxhG0d0M3c5dbpO8hUguxFfQ7/7oLxv0quuSszti1agonFXPfbePp?= =?us-ascii?Q?SxFnKNTuABU4qUu8/tntoHJTkwoaBzdN3vT2PvdfpE1Y82lXwwDwb8Q9hwMr?= =?us-ascii?Q?aJExw+5ZSNqdDzr/K8K01Cj2/jpy/oUVHu8RzlZ9CQ7YoyMPGuzHFb/IUyIF?= =?us-ascii?Q?bLPh7MBqzPKLAeMxdpZao/vNw4b7DUn/LqBnhypOh4iEc/M1rLBjLhZ7GXja?= =?us-ascii?Q?c07AzjLLkwFn6z7zjVYHDpU+lVnnnj6DhxTXEpYmnYcAcHWk/dI9fUFPEJ35?= =?us-ascii?Q?L+p4LZIlgLuCrt36TM9mW2DWZ01nm/YCpk4PJJZY3cxN2jU3+PkA5QkAeKG9?= =?us-ascii?Q?Vhlz0KjLqbEpZZGyo0B2OjCSYDGpc8r3WxIWuASfKdwtXNfkLhPaOQYEp14K?= =?us-ascii?Q?0pAGfn7/1grMopU/mgD4bfa0cIt1B2lj+JkLtcLMqWie/zsBHQ60Zy3TdIq/?= =?us-ascii?Q?8BkcuQgSJahUg6ubVnalXazuulYXXiicgJBBX2xQJZc9Tqv2QrTlVFMRbpVV?= =?us-ascii?Q?vFZ/ynJjjf62gGUj11Q6BiVQIc0aXbe5p1wn7P55vMSijXb4AB8YrwpsPiZl?= =?us-ascii?Q?/h+jjnffdRj6y7nsgIRZZ1wlUxhHM1LmHR4KBEfe9uVMqgyi2KUozfCrNpMZ?= =?us-ascii?Q?EXPGu48oY6VAd41xN+gKNt1Eun3vxRd9iTcJtdfDeLOqMQ2y0UoTtDK93rNl?= =?us-ascii?Q?jl4k5yNBmYHSTXDYxY2y1Pw8?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: BN6PR1101MB2147.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 428eb435-1be9-4783-dfbb-08d9523619f1 X-MS-Exchange-CrossTenant-originalarrivaltime: 29 Jul 2021 02:10:56.1811 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: Etko8fri8BPVzo7s2DwUtyVTZHVqPFXY0Igom3clucV6BW7urd/sjshECnH7PpfxLYM3XrL3VpVm5abRFv2US8jtImyeKqbWAxkYaNLIW7o= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN0PR11MB5760 Return-Path: nathaniel.l.desimone@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Nate DeSimone > -----Original Message----- > From: manickavasakam karpagavinayagam > Sent: Wednesday, June 16, 2021 2:48 PM > To: devel@edk2.groups.io > Cc: Oram, Isaac W ; Desimone, Nathaniel L > ; Felixp@ami.com; DOPPALAPUDI, > HARIKRISHNA ; Jha, Manish ; > Bobroff, Zachary ; KARPAGAVINAYAGAM, > MANICKAVASAKAM > Subject: [edk2-platforms] [PATCH V1 2/2] PurleyOpenBoardPkg : Override > generic PciBus Driver with Platform specific instance of PciBus driver. >=20 > Overriden generic PciBus Driver with Platform specific instance of PciBus > driver > To skip SPI controller initialization during PCI enumeration to avoid SET > variable > assert issue during POST > To skip executing a specific MLX card UEFI OPROM > Move > PurleyOpenBoardPkg/Override/edk2/MdeModulePkg/Bus/Pci/PciBusDxe to > PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBusDxe > --- > .../BoardTiogaPass/CoreDxeInclude.dsc | 5 +- > .../BoardTiogaPass/CoreUefiBootInclude.fdf | 5 +- > .../Bus/Pci/PciBusDxe/ComponentName.c | 170 + > .../Bus/Pci/PciBusDxe/ComponentName.h | 146 + > .../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c | 460 +++ > .../MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 396 +++ > .../Bus/Pci/PciBusDxe/PciBusDxe.inf | 112 + > .../Bus/Pci/PciBusDxe/PciBusDxe.uni | 16 + > .../Bus/Pci/PciBusDxe/PciBusDxeExtra.uni | 14 + > .../Bus/Pci/PciBusDxe/PciCommand.c | 267 ++ > .../Bus/Pci/PciBusDxe/PciCommand.h | 232 ++ > .../Bus/Pci/PciBusDxe/PciDeviceSupport.c | 1056 ++++++ > .../Bus/Pci/PciBusDxe/PciDeviceSupport.h | 266 ++ > .../Bus/Pci/PciBusDxe/PciDriverOverride.c | 188 ++ > .../Bus/Pci/PciBusDxe/PciDriverOverride.h | 83 + > .../Bus/Pci/PciBusDxe/PciEnumerator.c | 2210 +++++++++++++ > .../Bus/Pci/PciBusDxe/PciEnumerator.h | 515 +++ > .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 2885 > +++++++++++++++++ > .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h | 480 +++ > .../Bus/Pci/PciBusDxe/PciHotPlugSupport.c | 484 +++ > .../Bus/Pci/PciBusDxe/PciHotPlugSupport.h | 205 ++ > .../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 2087 ++++++++++++ > .../MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h | 660 ++++ > .../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c | 1809 +++++++++++ > .../MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h | 179 + > .../Bus/Pci/PciBusDxe/PciOptionRomSupport.c | 776 +++++ > .../Bus/Pci/PciBusDxe/PciOptionRomSupport.h | 136 + > .../Bus/Pci/PciBusDxe/PciPowerManagement.c | 82 + > .../Bus/Pci/PciBusDxe/PciPowerManagement.h | 28 + > .../Bus/Pci/PciBusDxe/PciResourceSupport.c | 2292 +++++++++++++ > .../Bus/Pci/PciBusDxe/PciResourceSupport.h | 456 +++ > .../Bus/Pci/PciBusDxe/PciRomTable.c | 135 + > .../Bus/Pci/PciBusDxe/PciRomTable.h | 48 + > 33 files changed, 18881 insertions(+), 2 deletions(-) > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/ComponentName.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/ComponentName.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciBus.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciBus.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciBusDxe.inf > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciBusDxe.uni > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciBusDxeExtra.uni > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciCommand.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciCommand.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciDeviceSupport.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciDeviceSupport.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciDriverOverride.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciDriverOverride.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciEnumerator.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciEnumerator.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciEnumeratorSupport.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciEnumeratorSupport.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciHotPlugSupport.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciHotPlugSupport.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciIo.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciIo.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciLib.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciLib.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciOptionRomSupport.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciOptionRomSupport.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciPowerManagement.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciPowerManagement.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciResourceSupport.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciResourceSupport.h > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciRomTable.c > create mode 100644 > Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/Pci > BusDxe/PciRomTable.h >=20 > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc > b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc > index 7dcb892dd5..b0660d72dd 100644 > --- > a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc > +++ > b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclude.dsc > @@ -78,7 +78,10 @@ > PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf >=20 > #MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf > - MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > +#TiogaPass Override START :Skip OPROM for specific Mellanox card & SPI > Controller > + #MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > + > $(PLATFORM_BOARD_PACKAGE)/Override/MdeModulePkg/Bus/Pci/PciBus > Dxe/PciBusDxe.inf > +#TiogaPass Override END >=20 > MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf > MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclud > e.fdf > b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclud > e.fdf > index 478a818546..141ce5dda3 100644 > --- > a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclud > e.fdf > +++ > b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclud > e.fdf > @@ -42,7 +42,10 @@ INF > MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntime > Dxe.inf > INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf >=20 > #INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf > -INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > +#TiogaPass Override START :Skip OPROM for specific Mellanox card & SPI > Controller > + #INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf > + INF > $(PLATFORM_BOARD_PACKAGE)/Override/MdeModulePkg/Bus/Pci/PciBus > Dxe/PciBusDxe.inf > +#TiogaPass Override END >=20 > INF MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf > INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/ComponentName.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/ComponentName.c > new file mode 100644 > index 0000000000..f3554507e2 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/ComponentName.c > @@ -0,0 +1,170 @@ > +/** @file > + EFI Component Name functions implementation for PCI Bus module. > + > +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +// > +// EFI Component Name Protocol > +// > +GLOBAL_REMOVE_IF_UNREFERENCED > EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName =3D { > + PciBusComponentNameGetDriverName, > + PciBusComponentNameGetControllerName, > + "eng" > +}; > + > +// > +// EFI Component Name 2 Protocol > +// > +GLOBAL_REMOVE_IF_UNREFERENCED > EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 =3D { > + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) > PciBusComponentNameGetDriverName, > + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) > PciBusComponentNameGetControllerName, > + "en" > +}; > + > + > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE > mPciBusDriverNameTable[] =3D { > + { "eng;en", (CHAR16 *) L"PCI Bus Driver" }, > + { NULL , NULL } > +}; > + > +/** > + Retrieves a Unicode string that is the user readable name of the drive= r. > + > + This function retrieves the user readable name of a driver in the form= of a > + Unicode string. If the driver specified by This has a user readable na= me in > + the language specified by Language, then a pointer to the driver name = is > + returned in DriverName, and EFI_SUCCESS is returned. If the driver > specified > + by This does not support the language specified by Language, > + then EFI_UNSUPPORTED is returned. > + > + @param This[in] A pointer to the > EFI_COMPONENT_NAME2_PROTOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + > + @param Language[in] A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is t= he > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied > + in RFC 4646 or ISO 639-2 language code f= ormat. > + > + @param DriverName[out] A pointer to the Unicode string to retur= n. > + This Unicode string is the name of the > + driver specified by This in the language > + specified by Language. > + > + @retval EFI_SUCCESS The Unicode string for the Driver specif= ied by > + This and the language specified by Langu= age was > + returned in DriverName. > + > + @retval EFI_INVALID_PARAMETER Language is NULL. > + > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > + > + @retval EFI_UNSUPPORTED The driver specified by This does not > support > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusComponentNameGetDriverName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ) > +{ > + return LookupUnicodeString2 ( > + Language, > + This->SupportedLanguages, > + mPciBusDriverNameTable, > + DriverName, > + (BOOLEAN)(This =3D=3D &gPciBusComponentName) > + ); > +} > + > +/** > + Retrieves a Unicode string that is the user readable name of the contr= oller > + that is being managed by a driver. > + > + This function retrieves the user readable name of the controller speci= fied > by > + ControllerHandle and ChildHandle in the form of a Unicode string. If t= he > + driver specified by This has a user readable name in the language spec= ified > by > + Language, then a pointer to the controller name is returned in > ControllerName, > + and EFI_SUCCESS is returned. If the driver specified by This is not c= urrently > + managing the controller specified by ControllerHandle and ChildHandle, > + then EFI_UNSUPPORTED is returned. If the driver specified by This doe= s > not > + support the language specified by Language, then EFI_UNSUPPORTED is > returned. > + > + @param This[in] A pointer to the > EFI_COMPONENT_NAME2_PROTOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + > + @param ControllerHandle[in] The handle of a controller that the driv= er > + specified by This is managing. This han= dle > + specifies the controller whose name is t= o be > + returned. > + > + @param ChildHandle[in] The handle of the child controller to re= trieve > + the name of. This is an optional parame= ter that > + may be NULL. It will be NULL for device > + drivers. It will also be NULL for a bus= drivers > + that wish to retrieve the name of the bu= s > + controller. It will not be NULL for a b= us > + driver that wishes to retrieve the name = of a > + child controller. > + > + @param Language[in] A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is = the > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied in > + RFC 4646 or ISO 639-2 language code form= at. > + > + @param ControllerName[out] A pointer to the Unicode string to retur= n. > + This Unicode string is the name of the > + controller specified by ControllerHandle= and > + ChildHandle in the language specified by > + Language from the point of view of the d= river > + specified by This. > + > + @retval EFI_SUCCESS The Unicode string for the user readable= name > in > + the language specified by Language for t= he > + driver specified by This was returned in > + DriverName. > + > + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. > + > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a > valid > + EFI_HANDLE. > + > + @retval EFI_INVALID_PARAMETER Language is NULL. > + > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > + > + @retval EFI_UNSUPPORTED The driver specified by This is not curr= ently > + managing the controller specified by > + ControllerHandle and ChildHandle. > + > + @retval EFI_UNSUPPORTED The driver specified by This does not > support > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusComponentNameGetControllerName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_HANDLE ChildHandle = OPTIONAL, > + IN CHAR8 *Language, > + OUT CHAR16 **ControllerName > + ) > +{ > + return EFI_UNSUPPORTED; > +} > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/ComponentName.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/ComponentName.h > new file mode 100644 > index 0000000000..fc3c672760 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/ComponentName.h > @@ -0,0 +1,146 @@ > +/** @file > + EFI Component Name functions declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > + > +#ifndef _EFI_PCI_BUS_COMPONENT_NAME_H_ > +#define _EFI_PCI_BUS_COMPONENT_NAME_H_ > + > +extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName; > +extern EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2; > + > +// > +// EFI Component Name Functions > +// > +/** > + Retrieves a Unicode string that is the user readable name of the drive= r. > + > + This function retrieves the user readable name of a driver in the form= of a > + Unicode string. If the driver specified by This has a user readable na= me in > + the language specified by Language, then a pointer to the driver name = is > + returned in DriverName, and EFI_SUCCESS is returned. If the driver > specified > + by This does not support the language specified by Language, > + then EFI_UNSUPPORTED is returned. > + > + @param This[in] A pointer to the > EFI_COMPONENT_NAME2_PROTOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + > + @param Language[in] A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is t= he > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied > + in RFC 4646 or ISO 639-2 language code f= ormat. > + > + @param DriverName[out] A pointer to the Unicode string to retur= n. > + This Unicode string is the name of the > + driver specified by This in the language > + specified by Language. > + > + @retval EFI_SUCCESS The Unicode string for the Driver specif= ied by > + This and the language specified by Langu= age was > + returned in DriverName. > + > + @retval EFI_INVALID_PARAMETER Language is NULL. > + > + @retval EFI_INVALID_PARAMETER DriverName is NULL. > + > + @retval EFI_UNSUPPORTED The driver specified by This does not > support > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusComponentNameGetDriverName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN CHAR8 *Language, > + OUT CHAR16 **DriverName > + ); > + > + > +/** > + Retrieves a Unicode string that is the user readable name of the contr= oller > + that is being managed by a driver. > + > + This function retrieves the user readable name of the controller speci= fied > by > + ControllerHandle and ChildHandle in the form of a Unicode string. If t= he > + driver specified by This has a user readable name in the language spec= ified > by > + Language, then a pointer to the controller name is returned in > ControllerName, > + and EFI_SUCCESS is returned. If the driver specified by This is not c= urrently > + managing the controller specified by ControllerHandle and ChildHandle, > + then EFI_UNSUPPORTED is returned. If the driver specified by This doe= s > not > + support the language specified by Language, then EFI_UNSUPPORTED is > returned. > + > + @param This[in] A pointer to the > EFI_COMPONENT_NAME2_PROTOCOL or > + EFI_COMPONENT_NAME_PROTOCOL instance. > + > + @param ControllerHandle[in] The handle of a controller that the driv= er > + specified by This is managing. This han= dle > + specifies the controller whose name is t= o be > + returned. > + > + @param ChildHandle[in] The handle of the child controller to re= trieve > + the name of. This is an optional parame= ter that > + may be NULL. It will be NULL for device > + drivers. It will also be NULL for a bus= drivers > + that wish to retrieve the name of the bu= s > + controller. It will not be NULL for a b= us > + driver that wishes to retrieve the name = of a > + child controller. > + > + @param Language[in] A pointer to a Null-terminated ASCII str= ing > + array indicating the language. This is = the > + language of the driver name that the cal= ler is > + requesting, and it must match one of the > + languages specified in SupportedLanguage= s. The > + number of languages supported by a drive= r is up > + to the driver writer. Language is specif= ied in > + RFC 4646 or ISO 639-2 language code form= at. > + > + @param ControllerName[out] A pointer to the Unicode string to retur= n. > + This Unicode string is the name of the > + controller specified by ControllerHandle= and > + ChildHandle in the language specified by > + Language from the point of view of the d= river > + specified by This. > + > + @retval EFI_SUCCESS The Unicode string for the user readable= name > in > + the language specified by Language for t= he > + driver specified by This was returned in > + DriverName. > + > + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. > + > + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a > valid > + EFI_HANDLE. > + > + @retval EFI_INVALID_PARAMETER Language is NULL. > + > + @retval EFI_INVALID_PARAMETER ControllerName is NULL. > + > + @retval EFI_UNSUPPORTED The driver specified by This is not curr= ently > + managing the controller specified by > + ControllerHandle and ChildHandle. > + > + @retval EFI_UNSUPPORTED The driver specified by This does not > support > + the language specified by Language. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusComponentNameGetControllerName ( > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > + IN EFI_HANDLE ControllerHandle, > + IN EFI_HANDLE ChildHandle = OPTIONAL, > + IN CHAR8 *Language, > + OUT CHAR16 **ControllerName > + ); > + > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBus.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBus.c > new file mode 100644 > index 0000000000..682b2dac38 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBus.c > @@ -0,0 +1,460 @@ > +/** @file > + Driver Binding functions for PCI Bus module. > + > + Single PCI bus driver instance will manager all PCI Root Bridges in on= e EFI > based firmware, > + since all PCI Root Bridges' resources need to be managed together. > + Supported() function will try to get PCI Root Bridge IO Protocol. > + Start() function will get PCI Host Bridge Resource Allocation Protocol= to > manage all > + PCI Root Bridges. So it means platform needs install PCI Root Bridge I= O > protocol for each > + PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +// > +// PCI Bus Driver Global Variables > +// > +EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding =3D { > + PciBusDriverBindingSupported, > + PciBusDriverBindingStart, > + PciBusDriverBindingStop, > + 0xa, > + NULL, > + NULL > +}; > + > +EFI_HANDLE > gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM]; > +EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL > *gIncompatiblePciDeviceSupport =3D NULL; > +UINTN gPciHostBridgeNumber =3D 0= ; > +BOOLEAN gFullEnumeration =3D T= RUE; > +UINT64 gAllOne =3D 0= xFFFFFFFFFFFFFFFFULL; > +UINT64 gAllZero =3D 0= ; > + > +EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; > +EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; > +EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; > +EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol; > + > +GLOBAL_REMOVE_IF_UNREFERENCED > EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest =3D { > + PciHotPlugRequestNotify > +}; > + > +/** > + The Entry Point for PCI Bus module. The user code starts with this fun= ction. > + > + Installs driver module protocols and. Creates virtual device handles f= or > ConIn, > + ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In E= x > protocol, > + Simple Pointer protocol, Absolute Pointer protocol on those virtual > handlers. > + Installs Graphics Output protocol and/or UGA Draw protocol if needed. > + > + @param[in] ImageHandle The firmware allocated handle for the EFI > image. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point is executed successfully. > + @retval other Some error occurred when executing this entr= y point. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE Handle; > + > + // > + // Initializes PCI devices pool > + // > + InitializePciDevicePool (); > + > + // > + // Install driver model protocol(s). > + // > + Status =3D EfiLibInstallDriverBindingComponentName2 ( > + ImageHandle, > + SystemTable, > + &gPciBusDriverBinding, > + ImageHandle, > + &gPciBusComponentName, > + &gPciBusComponentName2 > + ); > + ASSERT_EFI_ERROR (Status); > + > + if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + // > + // If Hot Plug is supported, install EFI PCI Hot Plug Request protoc= ol. > + // > + Handle =3D NULL; > + Status =3D gBS->InstallProtocolInterface ( > + &Handle, > + &gEfiPciHotPlugRequestProtocolGuid, > + EFI_NATIVE_INTERFACE, > + &mPciHotPlugRequest > + ); > + } > + > + return Status; > +} > + > +/** > + Test to see if this driver supports ControllerHandle. Any ControllerHa= ndle > + than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be > supported. > + > + @param This Protocol instance pointer. > + @param Controller Handle of device to test. > + @param RemainingDevicePath Optional parameter use to pick a specific > child > + device to start. > + > + @retval EFI_SUCCESS This driver supports this device. > + @retval EFI_ALREADY_STARTED This driver is already running on this > device. > + @retval other This driver does not support this device. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusDriverBindingSupported ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ) > +{ > + EFI_STATUS Status; > + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + EFI_DEV_PATH_PTR Node; > + > + // > + // Check RemainingDevicePath validation > + // > + if (RemainingDevicePath !=3D NULL) { > + // > + // Check if RemainingDevicePath is the End of Device Path Node, > + // if yes, go on checking other conditions > + // > + if (!IsDevicePathEnd (RemainingDevicePath)) { > + // > + // If RemainingDevicePath isn't the End of Device Path Node, > + // check its validation > + // > + Node.DevPath =3D RemainingDevicePath; > + if (Node.DevPath->Type !=3D HARDWARE_DEVICE_PATH || > + Node.DevPath->SubType !=3D HW_PCI_DP || > + DevicePathNodeLength(Node.DevPath) !=3D sizeof(PCI_DEVICE_PATH= )) > { > + return EFI_UNSUPPORTED; > + } > + } > + } > + > + // > + // Check if Pci Root Bridge IO protocol is installed by platform > + // > + Status =3D gBS->OpenProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo, > + This->DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (Status =3D=3D EFI_ALREADY_STARTED) { > + return EFI_SUCCESS; > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Close the I/O Abstraction(s) used to perform the supported test > + // > + gBS->CloseProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + This->DriverBindingHandle, > + Controller > + ); > + > + // > + // Open the EFI Device Path protocol needed to perform the supported > test > + // > + Status =3D gBS->OpenProtocol ( > + Controller, > + &gEfiDevicePathProtocolGuid, > + (VOID **) &ParentDevicePath, > + This->DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (Status =3D=3D EFI_ALREADY_STARTED) { > + return EFI_SUCCESS; > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Close protocol, don't use device path protocol in the Support() fun= ction > + // > + gBS->CloseProtocol ( > + Controller, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + Controller > + ); > + > + return EFI_SUCCESS; > +} > + > +/** > + Start this driver on ControllerHandle and enumerate Pci bus and start > + all device under PCI bus. > + > + @param This Protocol instance pointer. > + @param Controller Handle of device to bind driver to. > + @param RemainingDevicePath Optional parameter use to pick a specific > child > + device to start. > + > + @retval EFI_SUCCESS This driver is added to ControllerHandle. > + @retval EFI_ALREADY_STARTED This driver is already running on > ControllerHandle. > + @retval other This driver does not support this device. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusDriverBindingStart ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ) > +{ > + EFI_STATUS Status; > + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + > + // > + // Initialize PciRootBridgeIo to suppress incorrect compiler warning. > + // > + PciRootBridgeIo =3D NULL; > + > + // > + // Check RemainingDevicePath validation > + // > + if (RemainingDevicePath !=3D NULL) { > + // > + // Check if RemainingDevicePath is the End of Device Path Node, > + // if yes, return EFI_SUCCESS > + // > + if (IsDevicePathEnd (RemainingDevicePath)) { > + return EFI_SUCCESS; > + } > + } > + > + gBS->LocateProtocol ( > + &gEfiIncompatiblePciDeviceSupportProtocolGuid, > + NULL, > + (VOID **) &gIncompatiblePciDeviceSupport > + ); > + > + // > + // If PCI Platform protocol is available, get it now. > + // If the platform implements this, it must be installed before BDS ph= ase > + // > + gPciPlatformProtocol =3D NULL; > + gBS->LocateProtocol ( > + &gEfiPciPlatformProtocolGuid, > + NULL, > + (VOID **) &gPciPlatformProtocol > + ); > + > + // > + // If PCI Platform protocol doesn't exist, try to Pci Override Protoco= l. > + // > + if (gPciPlatformProtocol =3D=3D NULL) { > + gPciOverrideProtocol =3D NULL; > + gBS->LocateProtocol ( > + &gEfiPciOverrideProtocolGuid, > + NULL, > + (VOID **) &gPciOverrideProtocol > + ); > + } > + > + if (mIoMmuProtocol =3D=3D NULL) { > + gBS->LocateProtocol ( > + &gEdkiiIoMmuProtocolGuid, > + NULL, > + (VOID **) &mIoMmuProtocol > + ); > + } > + > + if (mDeviceSecurityProtocol =3D=3D NULL) { > + gBS->LocateProtocol ( > + &gEdkiiDeviceSecurityProtocolGuid, > + NULL, > + (VOID **) &mDeviceSecurityProtocol > + ); > + } > + > + if (PcdGetBool (PcdPciDisableBusEnumeration)) { > + gFullEnumeration =3D FALSE; > + } else { > + gFullEnumeration =3D (BOOLEAN) ((SearchHostBridgeHandle (Controller)= ? > FALSE : TRUE)); > + } > + > + // > + // Open Device Path Protocol for PCI root bridge > + // > + Status =3D gBS->OpenProtocol ( > + Controller, > + &gEfiDevicePathProtocolGuid, > + (VOID **) &ParentDevicePath, > + This->DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Report Status Code to indicate PCI bus starts > + // > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_PROGRESS_CODE, > + (EFI_IO_BUS_PCI | EFI_IOB_PC_INIT), > + ParentDevicePath > + ); > + > + Status =3D EFI_SUCCESS; > + // > + // Enumerate the entire host bridge > + // After enumeration, a database that records all the device informati= on > will be created > + // > + // > + if (gFullEnumeration) { > + // > + // Get the rootbridge Io protocol to find the host bridge handle > + // > + Status =3D gBS->OpenProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo, > + gPciBusDriverBinding.DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (!EFI_ERROR (Status)) { > + Status =3D PciEnumerator (Controller, PciRootBridgeIo->ParentHandl= e); > + } > + } else { > + // > + // If PCI bus has already done the full enumeration, never do it aga= in > + // > + Status =3D PciEnumeratorLight (Controller); > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Start all the devices under the entire host bridge. > + // > + StartPciDevices (Controller); > + > + if (gFullEnumeration) { > + gFullEnumeration =3D FALSE; > + > + Status =3D gBS->InstallProtocolInterface ( > + &PciRootBridgeIo->ParentHandle, > + &gEfiPciEnumerationCompleteProtocolGuid, > + EFI_NATIVE_INTERFACE, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + } > + > + return Status; > +} > + > +/** > + Stop this driver on ControllerHandle. Support stopping any child handl= es > + created by this driver. > + > + @param This Protocol instance pointer. > + @param Controller Handle of device to stop driver on. > + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If > number of > + children is zero stop the entire bus driver. > + @param ChildHandleBuffer List of Child Handles to Stop. > + > + @retval EFI_SUCCESS This driver is removed ControllerHandle. > + @retval other This driver was not removed from this device= . > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusDriverBindingStop ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN UINTN NumberOfChildren, > + IN EFI_HANDLE *ChildHandleBuffer > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + BOOLEAN AllChildrenStopped; > + > + if (NumberOfChildren =3D=3D 0) { > + // > + // Close the bus driver > + // > + gBS->CloseProtocol ( > + Controller, > + &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, > + Controller > + ); > + gBS->CloseProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + This->DriverBindingHandle, > + Controller > + ); > + > + DestroyRootBridgeByHandle ( > + Controller > + ); > + > + return EFI_SUCCESS; > + } > + > + // > + // Stop all the children > + // > + > + AllChildrenStopped =3D TRUE; > + > + for (Index =3D 0; Index < NumberOfChildren; Index++) { > + > + // > + // De register all the pci device > + // > + Status =3D DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]= ); > + > + if (EFI_ERROR (Status)) { > + AllChildrenStopped =3D FALSE; > + } > + } > + > + if (!AllChildrenStopped) { > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBus.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBus.h > new file mode 100644 > index 0000000000..967933e278 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBus.h > @@ -0,0 +1,396 @@ > +/** @file > + Header files and data structures needed by PCI Bus module. > + > +Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > + > +#ifndef _EFI_PCI_BUS_H_ > +#define _EFI_PCI_BUS_H_ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +typedef struct _PCI_IO_DEVICE PCI_IO_DEVICE; > +typedef struct _PCI_BAR PCI_BAR; > + > +#define EFI_PCI_RID(Bus, Device, Function) (((UINT32)Bus << 8) + > ((UINT32)Device << 3) + (UINT32)Function) > +#define EFI_PCI_BUS_OF_RID(RID) ((UINT32)RID >> 8) > + > +#define EFI_PCI_IOV_POLICY_ARI 0x0001 > +#define EFI_PCI_IOV_POLICY_SRIOV 0x0002 > +#define EFI_PCI_IOV_POLICY_MRIOV 0x0004 > + > +typedef enum { > + PciBarTypeUnknown =3D 0, > + PciBarTypeIo16, > + PciBarTypeIo32, > + PciBarTypeMem32, > + PciBarTypePMem32, > + PciBarTypeMem64, > + PciBarTypePMem64, > + PciBarTypeOpRom, > + PciBarTypeIo, > + PciBarTypeMem, > + PciBarTypeMaxType > +} PCI_BAR_TYPE; > + > +#include "ComponentName.h" > +#include "PciIo.h" > +#include "PciCommand.h" > +#include "PciDeviceSupport.h" > +#include "PciEnumerator.h" > +#include "PciEnumeratorSupport.h" > +#include "PciDriverOverride.h" > +#include "PciRomTable.h" > +#include "PciOptionRomSupport.h" > +#include "PciPowerManagement.h" > +#include "PciHotPlugSupport.h" > +#include "PciLib.h" > + > +#define VGABASE1 0x3B0 > +#define VGALIMIT1 0x3BB > + > +#define VGABASE2 0x3C0 > +#define VGALIMIT2 0x3DF > + > +#define ISABASE 0x100 > +#define ISALIMIT 0x3FF > + > +// > +// PCI BAR parameters > +// > +struct _PCI_BAR { > + UINT64 BaseAddress; > + UINT64 Length; > + UINT64 Alignment; > + PCI_BAR_TYPE BarType; > + BOOLEAN BarTypeFixed; > + UINT16 Offset; > +}; > + > +// > +// defined in PCI Card Specification, 8.0 > +// > +#define PCI_CARD_MEMORY_BASE_0 0x1C > +#define PCI_CARD_MEMORY_LIMIT_0 0x20 > +#define PCI_CARD_MEMORY_BASE_1 0x24 > +#define PCI_CARD_MEMORY_LIMIT_1 0x28 > +#define PCI_CARD_IO_BASE_0_LOWER 0x2C > +#define PCI_CARD_IO_BASE_0_UPPER 0x2E > +#define PCI_CARD_IO_LIMIT_0_LOWER 0x30 > +#define PCI_CARD_IO_LIMIT_0_UPPER 0x32 > +#define PCI_CARD_IO_BASE_1_LOWER 0x34 > +#define PCI_CARD_IO_BASE_1_UPPER 0x36 > +#define PCI_CARD_IO_LIMIT_1_LOWER 0x38 > +#define PCI_CARD_IO_LIMIT_1_UPPER 0x3A > +#define PCI_CARD_BRIDGE_CONTROL 0x3E > + > +#define PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE BIT8 > +#define PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE BIT9 > + > +#define RB_IO_RANGE 1 > +#define RB_MEM32_RANGE 2 > +#define RB_PMEM32_RANGE 3 > +#define RB_MEM64_RANGE 4 > +#define RB_PMEM64_RANGE 5 > + > +#define PPB_BAR_0 0 > +#define PPB_BAR_1 1 > +#define PPB_IO_RANGE 2 > +#define PPB_MEM32_RANGE 3 > +#define PPB_PMEM32_RANGE 4 > +#define PPB_PMEM64_RANGE 5 > +#define PPB_MEM64_RANGE 0xFF > + > +#define P2C_BAR_0 0 > +#define P2C_MEM_1 1 > +#define P2C_MEM_2 2 > +#define P2C_IO_1 3 > +#define P2C_IO_2 4 > + > +#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001 > +#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002 > +#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004 > +#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008 > +#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010 > +#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020 > +#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040 > + > +#define PCI_MAX_HOST_BRIDGE_NUM 0x0010 > + > +// > +// Define option for attribute > +// > +#define EFI_SET_SUPPORTS 0 > +#define EFI_SET_ATTRIBUTES 1 > + > +#define PCI_IO_DEVICE_SIGNATURE SIGNATURE_32 ('p', 'c', 'i= ', 'o') > + > +struct _PCI_IO_DEVICE { > + UINT32 Signature; > + EFI_HANDLE Handle; > + EFI_PCI_IO_PROTOCOL PciIo; > + LIST_ENTRY Link; > + > + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride; > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + EFI_LOAD_FILE2_PROTOCOL LoadFile2; > + > + // > + // PCI configuration space header type > + // > + PCI_TYPE00 Pci; > + > + // > + // Bus number, Device number, Function number > + // > + UINT8 BusNumber; > + UINT8 DeviceNumber; > + UINT8 FunctionNumber; > + > + // > + // BAR for this PCI Device > + // > + PCI_BAR PciBar[PCI_MAX_BAR]; > + > + // > + // The bridge device this pci device is subject to > + // > + PCI_IO_DEVICE *Parent; > + > + // > + // A linked list for children Pci Device if it is bridge device > + // > + LIST_ENTRY ChildList; > + > + // > + // TRUE if the PCI bus driver creates the handle for this PCI device > + // > + BOOLEAN Registered; > + > + // > + // TRUE if the PCI bus driver successfully allocates the resource requ= ired by > + // this PCI device > + // > + BOOLEAN Allocated; > + > + // > + // The attribute this PCI device currently set > + // > + UINT64 Attributes; > + > + // > + // The attributes this PCI device actually supports > + // > + UINT64 Supports; > + > + // > + // The resource decode the bridge supports > + // > + UINT32 Decodes; > + > + // > + // TRUE if the ROM image is from the PCI Option ROM BAR > + // > + BOOLEAN EmbeddedRom; > + > + // > + // The OptionRom Size > + // > + UINT32 RomSize; > + > + // > + // TRUE if all OpROM (in device or in platform specific position) have= been > processed > + // > + BOOLEAN AllOpRomProcessed; > + > + // > + // TRUE if there is any EFI driver in the OptionRom > + // > + BOOLEAN BusOverride; > + > + // > + // A list tracking reserved resource on a bridge device > + // > + LIST_ENTRY ReservedResourceList; > + > + // > + // A list tracking image handle of platform specific overriding driver > + // > + LIST_ENTRY OptionRomDriverList; > + > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR > *ResourcePaddingDescriptors; > + EFI_HPC_PADDING_ATTRIBUTES PaddingAttributes; > + > + // > + // Bus number ranges for a PCI Root Bridge device > + // > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges; > + > + BOOLEAN IsPciExp; > + // > + // For SR-IOV > + // > + UINT8 PciExpressCapabilityOffset; > + UINT32 AriCapabilityOffset; > + UINT32 SrIovCapabilityOffset; > + UINT32 MrIovCapabilityOffset; > + PCI_BAR VfPciBar[PCI_MAX_BAR]; > + UINT32 SystemPageSize; > + UINT16 InitialVFs; > + UINT16 ReservedBusNum; > + // > + // Per PCI to PCI Bridge spec, I/O window is 4K aligned, > + // but some chipsets support non-standard I/O window alignments less > than 4K. > + // This field is used to support this case. > + // > + UINT16 BridgeIoAlignment; > + UINT32 ResizableBarOffset; > + UINT32 ResizableBarNumber; > +}; > + > +#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ > + CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE) > + > +#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \ > + CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE) > + > +#define PCI_IO_DEVICE_FROM_LINK(a) \ > + CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE) > + > +#define PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS(a) \ > + CR (a, PCI_IO_DEVICE, LoadFile2, PCI_IO_DEVICE_SIGNATURE) > + > + > + > +// > +// Global Variables > +// > +extern EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL > *gIncompatiblePciDeviceSupport; > +extern EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding= ; > +extern EFI_COMPONENT_NAME_PROTOCOL > gPciBusComponentName; > +extern EFI_COMPONENT_NAME2_PROTOCOL > gPciBusComponentName2; > +extern BOOLEAN gFullEnumeration; > +extern UINTN gPciHostBridgeNumber= ; > +extern EFI_HANDLE > gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM]; > +extern UINT64 gAllOne; > +extern UINT64 gAllZero; > +extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtoco= l; > +extern EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtoco= l; > +extern BOOLEAN mReserveIsaAliases; > +extern BOOLEAN mReserveVgaAliases; > + > +/** > + Macro that checks whether device is a GFX device. > + > + @param _p Specified device. > + > + @retval TRUE Device is a GFX device. > + @retval FALSE Device is not a GFX device. > + > +**/ > +#define IS_PCI_GFX(_p) IS_CLASS2 (_p, PCI_CLASS_DISPLAY, > PCI_CLASS_DISPLAY_OTHER) > + > +/** > + Test to see if this driver supports ControllerHandle. Any ControllerHa= ndle > + than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be > supported. > + > + @param This Protocol instance pointer. > + @param Controller Handle of device to test. > + @param RemainingDevicePath Optional parameter use to pick a specific > child > + device to start. > + > + @retval EFI_SUCCESS This driver supports this device. > + @retval EFI_ALREADY_STARTED This driver is already running on this > device. > + @retval other This driver does not support this device. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusDriverBindingSupported ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ); > + > +/** > + Start this driver on ControllerHandle and enumerate Pci bus and start > + all device under PCI bus. > + > + @param This Protocol instance pointer. > + @param Controller Handle of device to bind driver to. > + @param RemainingDevicePath Optional parameter use to pick a specific > child > + device to start. > + > + @retval EFI_SUCCESS This driver is added to ControllerHandle. > + @retval EFI_ALREADY_STARTED This driver is already running on > ControllerHandle. > + @retval other This driver does not support this device. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusDriverBindingStart ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > + ); > + > +/** > + Stop this driver on ControllerHandle. Support stopping any child handl= es > + created by this driver. > + > + @param This Protocol instance pointer. > + @param Controller Handle of device to stop driver on. > + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If > number of > + children is zero stop the entire bus driver. > + @param ChildHandleBuffer List of Child Handles to Stop. > + > + @retval EFI_SUCCESS This driver is removed ControllerHandle. > + @retval other This driver was not removed from this device= . > + > +**/ > +EFI_STATUS > +EFIAPI > +PciBusDriverBindingStop ( > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > + IN EFI_HANDLE Controller, > + IN UINTN NumberOfChildren, > + IN EFI_HANDLE *ChildHandleBuffer > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxe.inf > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxe.inf > new file mode 100644 > index 0000000000..9d999f973b > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxe.inf > @@ -0,0 +1,112 @@ > +## @file > +# The PCI bus driver will probe all PCI devices and allocate MMIO and I= O > space for these devices. > +# Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable > hot plug supporting. > +# > +# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +# > +## > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D PciBusDxe > + MODULE_UNI_FILE =3D PciBusDxe.uni > + FILE_GUID =3D 93B80004-9FB3-11d4-9A3A-0090273FC14= D > + MODULE_TYPE =3D UEFI_DRIVER > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D PciBusEntryPoint > + > +# > +# The following information is for reference only and not required by th= e > build tools. > +# > +# VALID_ARCHITECTURES =3D IA32 X64 EBC ARM AARCH64 > +# > +# DRIVER_BINDING =3D gPciBusDriverBinding > +# COMPONENT_NAME =3D gPciBusComponentName > +# COMPONENT_NAME2 =3D gPciBusComponentName2 > +# > + > +[Sources] > + PciLib.c > + PciIo.c > + PciBus.c > + PciDeviceSupport.c > + ComponentName.c > + ComponentName.h > + PciCommand.c > + PciResourceSupport.c > + PciEnumeratorSupport.c > + PciEnumerator.c > + PciOptionRomSupport.c > + PciDriverOverride.c > + PciPowerManagement.c > + PciPowerManagement.h > + PciDriverOverride.h > + PciRomTable.c > + PciHotPlugSupport.c > + PciLib.h > + PciHotPlugSupport.h > + PciRomTable.h > + PciOptionRomSupport.h > + PciEnumeratorSupport.h > + PciEnumerator.h > + PciResourceSupport.h > + PciDeviceSupport.h > + PciCommand.h > + PciIo.h > + PciBus.h > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > +[LibraryClasses] > + PcdLib > + DevicePathLib > + UefiBootServicesTableLib > + MemoryAllocationLib > + ReportStatusCodeLib > + BaseMemoryLib > + UefiLib > + BaseLib > + UefiDriverEntryPoint > + DebugLib > + > +[Protocols] > + gEfiPciHotPlugRequestProtocolGuid ## SOMETIMES_PRODUCES > + gEfiPciIoProtocolGuid ## BY_START > + gEfiDevicePathProtocolGuid ## BY_START > + gEfiBusSpecificDriverOverrideProtocolGuid ## BY_START > + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES > + gEfiDecompressProtocolGuid ## SOMETIMES_CONSUMES > + gEfiPciHotPlugInitProtocolGuid ## SOMETIMES_CONSUMES > + gEfiPciHostBridgeResourceAllocationProtocolGuid ## TO_START > + gEfiPciPlatformProtocolGuid ## SOMETIMES_CONSUMES > + gEfiPciOverrideProtocolGuid ## SOMETIMES_CONSUMES > + gEfiPciEnumerationCompleteProtocolGuid ## PRODUCES > + gEfiPciRootBridgeIoProtocolGuid ## TO_START > + gEfiIncompatiblePciDeviceSupportProtocolGuid ## > SOMETIMES_CONSUMES > + gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES > + gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES > + gEdkiiDeviceSecurityProtocolGuid ## SOMETIMES_CONSUMES > + gEdkiiDeviceIdentifierTypePciGuid ## SOMETIMES_CONSUMES > + gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES > + > +[FeaturePcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport > ## CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdPciBridgeIoAlignmentProbe ## > CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdUnalignedPciIoEnable ## > CONSUMES > + > gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeResourceForOptionRom > ## CONSUMES > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize ## > SOMETIMES_CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport ## > CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport ## > CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport ## > CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration ## > SOMETIMES_CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarSupport ## > CONSUMES > + > +[UserExtensions.TianoCore."ExtraFiles"] > + PciBusDxeExtra.uni > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxe.uni > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxe.uni > new file mode 100644 > index 0000000000..81bfc2c9ef > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxe.uni > @@ -0,0 +1,16 @@ > +// /** @file > +// The PCI bus driver will probe all PCI devices and allocate MMIO and I= O > space for these devices. > +// > +// Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable > hot plug supporting. > +// > +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. > +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US "Probes all PCI > devices and allocate MMIO and IO space for these devices" > + > +#string STR_MODULE_DESCRIPTION #language en-US "Please use PCD > feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.= " > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxeExtra.uni > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxeExtra.uni > new file mode 100644 > index 0000000000..f6a7cdae00 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciBusDxeExtra.uni > @@ -0,0 +1,14 @@ > +// /** @file > +// PciBusDxe Localized Strings and Content > +// > +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. > +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > +#string STR_PROPERTIES_MODULE_NAME > +#language en-US > +"PCI Bus DXE Driver" > + > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciCommand.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciCommand.c > new file mode 100644 > index 0000000000..3111448643 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciCommand.c > @@ -0,0 +1,267 @@ > +/** @file > + PCI command register operations supporting functions implementation fo= r > PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +/** > + Operate the PCI register via PciIo function interface. > + > + @param PciIoDevice Pointer to instance of PCI_IO_DEVICE. > + @param Command Operator command. > + @param Offset The address within the PCI configuration space f= or the > PCI controller. > + @param Operation Type of Operation. > + @param PtrCommand Return buffer holding old PCI command, if > operation is not EFI_SET_REGISTER. > + > + @return Status of PciIo operation. > + > +**/ > +EFI_STATUS > +PciOperateRegister ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT16 Command, > + IN UINT8 Offset, > + IN UINT8 Operation, > + OUT UINT16 *PtrCommand > + ) > +{ > + UINT16 OldCommand; > + EFI_STATUS Status; > + EFI_PCI_IO_PROTOCOL *PciIo; > + > + OldCommand =3D 0; > + PciIo =3D &PciIoDevice->PciIo; > + > + if (Operation !=3D EFI_SET_REGISTER) { > + Status =3D PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + Offset, > + 1, > + &OldCommand > + ); > + > + if (Operation =3D=3D EFI_GET_REGISTER) { > + *PtrCommand =3D OldCommand; > + return Status; > + } > + } > + > + if (Operation =3D=3D EFI_ENABLE_REGISTER) { > + OldCommand =3D (UINT16) (OldCommand | Command); > + } else if (Operation =3D=3D EFI_DISABLE_REGISTER) { > + OldCommand =3D (UINT16) (OldCommand & ~(Command)); > + } else { > + OldCommand =3D Command; > + } > + > + return PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + Offset, > + 1, > + &OldCommand > + ); > +} > + > +/** > + Check the capability supporting by given device. > + > + @param PciIoDevice Pointer to instance of PCI_IO_DEVICE. > + > + @retval TRUE Capability supported. > + @retval FALSE Capability not supported. > + > +**/ > +BOOLEAN > +PciCapabilitySupport ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + if ((PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) !=3D 0) = { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + Locate capability register block per capability ID. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param CapId The capability ID. > + @param Offset A pointer to the offset returned. > + @param NextRegBlock A pointer to the next block returned. > + > + @retval EFI_SUCCESS Successfully located capability register bloc= k. > + @retval EFI_UNSUPPORTED Pci device does not support capability. > + @retval EFI_NOT_FOUND Pci device support but can not find register > block. > + > +**/ > +EFI_STATUS > +LocateCapabilityRegBlock ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 CapId, > + IN OUT UINT8 *Offset, > + OUT UINT8 *NextRegBlock OPTIONAL > + ) > +{ > + UINT8 CapabilityPtr; > + UINT16 CapabilityEntry; > + UINT8 CapabilityID; > + > + // > + // To check the capability of this device supports > + // > + if (!PciCapabilitySupport (PciIoDevice)) { > + return EFI_UNSUPPORTED; > + } > + > + if (*Offset !=3D 0) { > + CapabilityPtr =3D *Offset; > + } else { > + > + CapabilityPtr =3D 0; > + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { > + > + PciIoDevice->PciIo.Pci.Read ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint8, > + EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR, > + 1, > + &CapabilityPtr > + ); > + } else { > + > + PciIoDevice->PciIo.Pci.Read ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint8, > + PCI_CAPBILITY_POINTER_OFFSET, > + 1, > + &CapabilityPtr > + ); > + } > + } > + > + while ((CapabilityPtr >=3D 0x40) && ((CapabilityPtr & 0x03) =3D=3D 0x0= 0)) { > + PciIoDevice->PciIo.Pci.Read ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint16, > + CapabilityPtr, > + 1, > + &CapabilityEntry > + ); > + > + CapabilityID =3D (UINT8) CapabilityEntry; > + > + if (CapabilityID =3D=3D CapId) { > + *Offset =3D CapabilityPtr; > + if (NextRegBlock !=3D NULL) { > + *NextRegBlock =3D (UINT8) (CapabilityEntry >> 8); > + } > + > + return EFI_SUCCESS; > + } > + > + // > + // Certain PCI device may incorrectly have capability pointing to it= self, > + // break to avoid dead loop. > + // > + if (CapabilityPtr =3D=3D (UINT8) (CapabilityEntry >> 8)) { > + break; > + } > + > + CapabilityPtr =3D (UINT8) (CapabilityEntry >> 8); > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + Locate PciExpress capability register block per capability ID. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param CapId The capability ID. > + @param Offset A pointer to the offset returned. > + @param NextRegBlock A pointer to the next block returned. > + > + @retval EFI_SUCCESS Successfully located capability register bloc= k. > + @retval EFI_UNSUPPORTED Pci device does not support capability. > + @retval EFI_NOT_FOUND Pci device support but can not find register > block. > + > +**/ > +EFI_STATUS > +LocatePciExpressCapabilityRegBlock ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT16 CapId, > + IN OUT UINT32 *Offset, > + OUT UINT32 *NextRegBlock OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + UINT32 CapabilityPtr; > + UINT32 CapabilityEntry; > + UINT16 CapabilityID; > + > + // > + // To check the capability of this device supports > + // > + if (!PciIoDevice->IsPciExp) { > + return EFI_UNSUPPORTED; > + } > + > + if (*Offset !=3D 0) { > + CapabilityPtr =3D *Offset; > + } else { > + CapabilityPtr =3D EFI_PCIE_CAPABILITY_BASE_OFFSET; > + } > + > + while (CapabilityPtr !=3D 0) { > + // > + // Mask it to DWORD alignment per PCI spec > + // > + CapabilityPtr &=3D 0xFFC; > + Status =3D PciIoDevice->PciIo.Pci.Read ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint32, > + CapabilityPtr, > + 1, > + &CapabilityEntry > + ); > + if (EFI_ERROR (Status)) { > + break; > + } > + > + if (CapabilityEntry =3D=3D MAX_UINT32) { > + DEBUG (( > + DEBUG_WARN, > + "%a: [%02x|%02x|%02x] failed to access config space at offset 0x= %x\n", > + __FUNCTION__, > + PciIoDevice->BusNumber, > + PciIoDevice->DeviceNumber, > + PciIoDevice->FunctionNumber, > + CapabilityPtr > + )); > + break; > + } > + > + CapabilityID =3D (UINT16) CapabilityEntry; > + > + if (CapabilityID =3D=3D CapId) { > + *Offset =3D CapabilityPtr; > + if (NextRegBlock !=3D NULL) { > + *NextRegBlock =3D (CapabilityEntry >> 20) & 0xFFF; > + } > + > + return EFI_SUCCESS; > + } > + > + CapabilityPtr =3D (CapabilityEntry >> 20) & 0xFFF; > + } > + > + return EFI_NOT_FOUND; > +} > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciCommand.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciCommand.h > new file mode 100644 > index 0000000000..5eabd56bf2 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciCommand.h > @@ -0,0 +1,232 @@ > +/** @file > + PCI command register operations supporting functions declaration for P= CI > Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > + > +#ifndef _EFI_PCI_COMMAND_H_ > +#define _EFI_PCI_COMMAND_H_ > + > +// > +// The PCI Command register bits owned by PCI Bus driver. > +// > +// They should be cleared at the beginning. The other registers > +// are owned by chipset, we should not touch them. > +// > +#define EFI_PCI_COMMAND_BITS_OWNED ( \ > + EFI_PCI_COMMAND_IO_SPACE | \ > + EFI_PCI_COMMAND_MEMORY_SPACE | \ > + EFI_PCI_COMMAND_BUS_MASTER | \ > + EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \ > + EFI_PCI_COMMAND_VGA_PALETTE_SNOOP | \ > + EFI_PCI_COMMAND_FAST_BACK_TO_BACK \ > + ) > + > +// > +// The PCI Bridge Control register bits owned by PCI Bus driver. > +// > +// They should be cleared at the beginning. The other registers > +// are owned by chipset, we should not touch them. > +// > +#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED ( \ > + EFI_PCI_BRIDGE_CONTROL_ISA | \ > + EFI_PCI_BRIDGE_CONTROL_VGA | \ > + EFI_PCI_BRIDGE_CONTROL_VGA_16 | \ > + EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \ > + ) > + > +// > +// The PCCard Bridge Control register bits owned by PCI Bus driver. > +// > +// They should be cleared at the beginning. The other registers > +// are owned by chipset, we should not touch them. > +// > +#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED ( \ > + EFI_PCI_BRIDGE_CONTROL_ISA | \ > + EFI_PCI_BRIDGE_CONTROL_VGA | \ > + EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \ > + ) > + > + > +#define EFI_GET_REGISTER 1 > +#define EFI_SET_REGISTER 2 > +#define EFI_ENABLE_REGISTER 3 > +#define EFI_DISABLE_REGISTER 4 > + > +/** > + Operate the PCI register via PciIo function interface. > + > + @param PciIoDevice Pointer to instance of PCI_IO_DEVICE. > + @param Command Operator command. > + @param Offset The address within the PCI configuration space f= or the > PCI controller. > + @param Operation Type of Operation. > + @param PtrCommand Return buffer holding old PCI command, if > operation is not EFI_SET_REGISTER. > + > + @return Status of PciIo operation. > + > +**/ > +EFI_STATUS > +PciOperateRegister ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT16 Command, > + IN UINT8 Offset, > + IN UINT8 Operation, > + OUT UINT16 *PtrCommand > + ); > + > +/** > + Check the capability supporting by given device. > + > + @param PciIoDevice Pointer to instance of PCI_IO_DEVICE. > + > + @retval TRUE Capability supported. > + @retval FALSE Capability not supported. > + > +**/ > +BOOLEAN > +PciCapabilitySupport ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Locate capability register block per capability ID. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param CapId The capability ID. > + @param Offset A pointer to the offset returned. > + @param NextRegBlock A pointer to the next block returned. > + > + @retval EFI_SUCCESS Successfully located capability register bloc= k. > + @retval EFI_UNSUPPORTED Pci device does not support capability. > + @retval EFI_NOT_FOUND Pci device support but can not find register > block. > + > +**/ > +EFI_STATUS > +LocateCapabilityRegBlock ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 CapId, > + IN OUT UINT8 *Offset, > + OUT UINT8 *NextRegBlock OPTIONAL > + ); > + > +/** > + Locate PciExpress capability register block per capability ID. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param CapId The capability ID. > + @param Offset A pointer to the offset returned. > + @param NextRegBlock A pointer to the next block returned. > + > + @retval EFI_SUCCESS Successfully located capability register bloc= k. > + @retval EFI_UNSUPPORTED Pci device does not support capability. > + @retval EFI_NOT_FOUND Pci device support but can not find register > block. > + > +**/ > +EFI_STATUS > +LocatePciExpressCapabilityRegBlock ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT16 CapId, > + IN OUT UINT32 *Offset, > + OUT UINT32 *NextRegBlock OPTIONAL > + ); > + > +/** > + Macro that reads command register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[out] Pointer to the 16-bit value read from command > register. > + > + @return status of PciIo operation > + > +**/ > +#define PCI_READ_COMMAND_REGISTER(a,b) \ > + PciOperateRegister (a, 0, PCI_COMMAND_OFFSET, EFI_GET_REGISTER, > b) > + > +/** > + Macro that writes command register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[in] The 16-bit value written into command register= . > + > + @return status of PciIo operation > + > +**/ > +#define PCI_SET_COMMAND_REGISTER(a,b) \ > + PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_SET_REGISTER, > NULL) > + > +/** > + Macro that enables command register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[in] The enabled value written into command registe= r. > + > + @return status of PciIo operation > + > +**/ > +#define PCI_ENABLE_COMMAND_REGISTER(a,b) \ > + PciOperateRegister (a, b, PCI_COMMAND_OFFSET, > EFI_ENABLE_REGISTER, NULL) > + > +/** > + Macro that disables command register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[in] The disabled value written into command regist= er. > + > + @return status of PciIo operation > + > +**/ > +#define PCI_DISABLE_COMMAND_REGISTER(a,b) \ > + PciOperateRegister (a, b, PCI_COMMAND_OFFSET, > EFI_DISABLE_REGISTER, NULL) > + > +/** > + Macro that reads PCI bridge control register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[out] The 16-bit value read from control register. > + > + @return status of PciIo operation > + > +**/ > +#define PCI_READ_BRIDGE_CONTROL_REGISTER(a,b) \ > + PciOperateRegister (a, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, > EFI_GET_REGISTER, b) > + > +/** > + Macro that writes PCI bridge control register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[in] The 16-bit value written into control register= . > + > + @return status of PciIo operation > + > +**/ > +#define PCI_SET_BRIDGE_CONTROL_REGISTER(a,b) \ > + PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, > EFI_SET_REGISTER, NULL) > + > +/** > + Macro that enables PCI bridge control register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[in] The enabled value written into command registe= r. > + > + @return status of PciIo operation > + > +**/ > +#define PCI_ENABLE_BRIDGE_CONTROL_REGISTER(a,b) \ > + PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, > EFI_ENABLE_REGISTER, NULL) > + > +/** > + Macro that disables PCI bridge control register. > + > + @param a[in] Pointer to instance of PCI_IO_DEVICE. > + @param b[in] The disabled value written into command regist= er. > + > + @return status of PciIo operation > + > +**/ > +#define PCI_DISABLE_BRIDGE_CONTROL_REGISTER(a,b) \ > + PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, > EFI_DISABLE_REGISTER, NULL) > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDeviceSupport.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDeviceSupport.c > new file mode 100644 > index 0000000000..7effbd5053 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDeviceSupport.c > @@ -0,0 +1,1056 @@ > +/** @file > + Supporting functions implementation for PCI devices management. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +(C) Copyright 2018 Hewlett Packard Enterprise Development LP
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +// > +// This device structure is serviced as a header. > +// Its next field points to the first root bridge device node. > +// > +LIST_ENTRY mPciDevicePool; > + > +/** > + Initialize the PCI devices pool. > + > +**/ > +VOID > +InitializePciDevicePool ( > + VOID > + ) > +{ > + InitializeListHead (&mPciDevicePool); > +} > + > +/** > + Insert a root bridge into PCI device pool. > + > + @param RootBridge A pointer to the PCI_IO_DEVICE. > + > +**/ > +VOID > +InsertRootBridge ( > + IN PCI_IO_DEVICE *RootBridge > + ) > +{ > + InsertTailList (&mPciDevicePool, &(RootBridge->Link)); > +} > + > +/** > + This function is used to insert a PCI device node under > + a bridge. > + > + @param Bridge The PCI bridge. > + @param PciDeviceNode The PCI device needs inserting. > + > +**/ > +VOID > +InsertPciDevice ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_IO_DEVICE *PciDeviceNode > + ) > +{ > + InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link)); > + PciDeviceNode->Parent =3D Bridge; > +} > + > +/** > + Destroy root bridge and remove it from device tree. > + > + @param RootBridge The bridge want to be removed. > + > +**/ > +VOID > +DestroyRootBridge ( > + IN PCI_IO_DEVICE *RootBridge > + ) > +{ > + DestroyPciDeviceTree (RootBridge); > + > + FreePciDevice (RootBridge); > +} > + > +/** > + Destroy a pci device node. > + > + All direct or indirect allocated resource for this node will be freed. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE to be destroyed. > + > +**/ > +VOID > +FreePciDevice ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + ASSERT (PciIoDevice !=3D NULL); > + // > + // Assume all children have been removed underneath this device > + // > + if (PciIoDevice->ResourcePaddingDescriptors !=3D NULL) { > + FreePool (PciIoDevice->ResourcePaddingDescriptors); > + } > + > + if (PciIoDevice->DevicePath !=3D NULL) { > + FreePool (PciIoDevice->DevicePath); > + } > + > + if (PciIoDevice->BusNumberRanges !=3D NULL) { > + FreePool (PciIoDevice->BusNumberRanges); > + } > + > + FreePool (PciIoDevice); > +} > + > +/** > + Destroy all the pci device node under the bridge. > + Bridge itself is not included. > + > + @param Bridge A pointer to the PCI_IO_DEVICE. > + > +**/ > +VOID > +DestroyPciDeviceTree ( > + IN PCI_IO_DEVICE *Bridge > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *Temp; > + > + while (!IsListEmpty (&Bridge->ChildList)) { > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + // > + // Remove this node from the linked list > + // > + RemoveEntryList (CurrentLink); > + > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (!IsListEmpty (&Temp->ChildList)) { > + DestroyPciDeviceTree (Temp); > + } > + > + FreePciDevice (Temp); > + } > +} > + > +/** > + Destroy all device nodes under the root bridge > + specified by Controller. > + > + The root bridge itself is also included. > + > + @param Controller Root bridge handle. > + > + @retval EFI_SUCCESS Destroy all device nodes successfully. > + @retval EFI_NOT_FOUND Cannot find any PCI device under specified > + root bridge. > + > +**/ > +EFI_STATUS > +DestroyRootBridgeByHandle ( > + IN EFI_HANDLE Controller > + ) > +{ > + > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *Temp; > + > + CurrentLink =3D mPciDevicePool.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &mPciDevicePool) { > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (Temp->Handle =3D=3D Controller) { > + > + RemoveEntryList (CurrentLink); > + > + DestroyPciDeviceTree (Temp); > + > + FreePciDevice (Temp); > + > + return EFI_SUCCESS; > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This function registers the PCI IO device. > + > + It creates a handle for this PCI IO device (if the handle does not exi= st), > attaches > + appropriate protocols onto the handle, does necessary initialization, = and > sets up > + parent/child relationship with its bus controller. > + > + @param Controller An EFI handle for the PCI bus controller. > + @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to = be > registered. > + @param Handle A pointer to hold the returned EFI handle for th= e PCI > IO device. > + > + @retval EFI_SUCCESS The PCI device is successfully registered. > + @retval other An error occurred when registering the PCI devic= e. > + > +**/ > +EFI_STATUS > +RegisterPciDevice ( > + IN EFI_HANDLE Controller, > + IN PCI_IO_DEVICE *PciIoDevice, > + OUT EFI_HANDLE *Handle OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + VOID *PlatformOpRomBuffer; > + UINTN PlatformOpRomSize; > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT8 Data8; > + BOOLEAN HasEfiImage; > + > + // > + // Install the pciio protocol, device path protocol > + // > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &PciIoDevice->Handle, > + &gEfiDevicePathProtocolGuid, > + PciIoDevice->DevicePath, > + &gEfiPciIoProtocolGuid, > + &PciIoDevice->PciIo, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Force Interrupt line to "Unknown" or "No Connection" > + // > + PciIo =3D &(PciIoDevice->PciIo); > + Data8 =3D PCI_INT_LINE_UNKNOWN; > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8); > + > + // > + // Process OpRom > + // > + if (!PciIoDevice->AllOpRomProcessed) { > + > + // > + // Get the OpRom provided by platform > + // > + if (gPciPlatformProtocol !=3D NULL) { > + Status =3D gPciPlatformProtocol->GetPciRom ( > + gPciPlatformProtocol, > + PciIoDevice->Handle, > + &PlatformOpRomBuffer, > + &PlatformOpRomSize > + ); > + if (!EFI_ERROR (Status)) { > + PciIoDevice->EmbeddedRom =3D FALSE; > + PciIoDevice->RomSize =3D (UINT32) PlatformOpRomSize; > + PciIoDevice->PciIo.RomSize =3D PlatformOpRomSize; > + PciIoDevice->PciIo.RomImage =3D PlatformOpRomBuffer; > + // > + // For OpROM read from gPciPlatformProtocol: > + // Add the Rom Image to internal database for later PCI light > enumeration > + // > + PciRomAddImageMapping ( > + NULL, > + PciIoDevice->PciRootBridgeIo->SegmentNumber, > + PciIoDevice->BusNumber, > + PciIoDevice->DeviceNumber, > + PciIoDevice->FunctionNumber, > + PciIoDevice->PciIo.RomImage, > + PciIoDevice->PciIo.RomSize > + ); > + } > + } else if (gPciOverrideProtocol !=3D NULL) { > + Status =3D gPciOverrideProtocol->GetPciRom ( > + gPciOverrideProtocol, > + PciIoDevice->Handle, > + &PlatformOpRomBuffer, > + &PlatformOpRomSize > + ); > + if (!EFI_ERROR (Status)) { > + PciIoDevice->EmbeddedRom =3D FALSE; > + PciIoDevice->RomSize =3D (UINT32) PlatformOpRomSize; > + PciIoDevice->PciIo.RomSize =3D PlatformOpRomSize; > + PciIoDevice->PciIo.RomImage =3D PlatformOpRomBuffer; > + // > + // For OpROM read from gPciOverrideProtocol: > + // Add the Rom Image to internal database for later PCI light > enumeration > + // > + PciRomAddImageMapping ( > + NULL, > + PciIoDevice->PciRootBridgeIo->SegmentNumber, > + PciIoDevice->BusNumber, > + PciIoDevice->DeviceNumber, > + PciIoDevice->FunctionNumber, > + PciIoDevice->PciIo.RomImage, > + PciIoDevice->PciIo.RomSize > + ); > + } > + } > + } > + > + // > + // Determine if there are EFI images in the option rom > + // > + HasEfiImage =3D ContainEfiImage (PciIoDevice->PciIo.RomImage, > PciIoDevice->PciIo.RomSize); > + > + if (HasEfiImage) { > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &PciIoDevice->Handle, > + &gEfiLoadFile2ProtocolGuid, > + &PciIoDevice->LoadFile2, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + gBS->UninstallMultipleProtocolInterfaces ( > + PciIoDevice->Handle, > + &gEfiDevicePathProtocolGuid, > + PciIoDevice->DevicePath, > + &gEfiPciIoProtocolGuid, > + &PciIoDevice->PciIo, > + NULL > + ); > + return Status; > + } > + } > + > + > + if (!PciIoDevice->AllOpRomProcessed) { > + > + PciIoDevice->AllOpRomProcessed =3D TRUE; > + > + // > + // Dispatch the EFI OpRom for the PCI device. > + // The OpRom is got from platform in the above code > + // or loaded from device in the previous round of bus enumeration > + // > + if (HasEfiImage) { > + ProcessOpRomImage (PciIoDevice); > + } > + } > + > + if (PciIoDevice->BusOverride) { > + // > + // Install Bus Specific Driver Override Protocol > + // > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &PciIoDevice->Handle, > + &gEfiBusSpecificDriverOverrideProtocolGuid, > + &PciIoDevice->PciDriverOverride, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + gBS->UninstallMultipleProtocolInterfaces ( > + PciIoDevice->Handle, > + &gEfiDevicePathProtocolGuid, > + PciIoDevice->DevicePath, > + &gEfiPciIoProtocolGuid, > + &PciIoDevice->PciIo, > + NULL > + ); > + if (HasEfiImage) { > + gBS->UninstallMultipleProtocolInterfaces ( > + PciIoDevice->Handle, > + &gEfiLoadFile2ProtocolGuid, > + &PciIoDevice->LoadFile2, > + NULL > + ); > + } > + > + return Status; > + } > + } > + > + Status =3D gBS->OpenProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &(PciIoDevice->PciRootBridgeIo), > + gPciBusDriverBinding.DriverBindingHandle, > + PciIoDevice->Handle, > + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (Handle !=3D NULL) { > + *Handle =3D PciIoDevice->Handle; > + } > + > + // > + // Indicate the pci device is registered > + // > + PciIoDevice->Registered =3D TRUE; > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is used to remove the whole PCI devices on the specified > bridge from > + the root bridge. > + > + @param RootBridgeHandle The root bridge device handle. > + @param Bridge The bridge device to be removed. > + > +**/ > +VOID > +RemoveAllPciDeviceOnBridge ( > + EFI_HANDLE RootBridgeHandle, > + PCI_IO_DEVICE *Bridge > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *Temp; > + > + while (!IsListEmpty (&Bridge->ChildList)) { > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + // > + // Check if the current node has been deregistered before > + // If it is not, then deregister it > + // > + if (Temp->Registered) { > + DeRegisterPciDevice (RootBridgeHandle, Temp->Handle); > + } > + > + // > + // Remove this node from the linked list > + // > + RemoveEntryList (CurrentLink); > + > + if (!IsListEmpty (&Temp->ChildList)) { > + RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp); > + } > + > + FreePciDevice (Temp); > + } > +} > + > +/** > + This function is used to de-register the PCI IO device. > + > + That includes un-installing PciIo protocol from the specified PCI > + device handle. > + > + @param Controller An EFI handle for the PCI bus controller. > + @param Handle PCI device handle. > + > + @retval EFI_SUCCESS The PCI device is successfully de-registered. > + @retval other An error occurred when de-registering the PCI dev= ice. > + > +**/ > +EFI_STATUS > +DeRegisterPciDevice ( > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE Handle > + ) > + > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + PCI_IO_DEVICE *Node; > + LIST_ENTRY *CurrentLink; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + > + Status =3D gBS->OpenProtocol ( > + Handle, > + &gEfiPciIoProtocolGuid, > + (VOID **) &PciIo, > + gPciBusDriverBinding.DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (!EFI_ERROR (Status)) { > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); > + > + // > + // If it is already de-registered > + // > + if (!PciIoDevice->Registered) { > + return EFI_SUCCESS; > + } > + > + // > + // If it is PPB, first de-register its children > + // > + > + if (!IsListEmpty (&PciIoDevice->ChildList)) { > + > + CurrentLink =3D PciIoDevice->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &PciIoDevice->Chi= ldList) { > + Node =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + Status =3D DeRegisterPciDevice (Controller, Node->Handle); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + } > + > + // > + // Close the child handle > + // > + Status =3D gBS->CloseProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + gPciBusDriverBinding.DriverBindingHandle, > + Handle > + ); > + > + // > + // Un-install the Device Path protocol and PCI I/O protocol > + // and Bus Specific Driver Override protocol if needed. > + // > + if (PciIoDevice->BusOverride) { > + Status =3D gBS->UninstallMultipleProtocolInterfaces ( > + Handle, > + &gEfiDevicePathProtocolGuid, > + PciIoDevice->DevicePath, > + &gEfiPciIoProtocolGuid, > + &PciIoDevice->PciIo, > + &gEfiBusSpecificDriverOverrideProtocolGuid, > + &PciIoDevice->PciDriverOverride, > + NULL > + ); > + } else { > + Status =3D gBS->UninstallMultipleProtocolInterfaces ( > + Handle, > + &gEfiDevicePathProtocolGuid, > + PciIoDevice->DevicePath, > + &gEfiPciIoProtocolGuid, > + &PciIoDevice->PciIo, > + NULL > + ); > + } > + > + if (!EFI_ERROR (Status)) { > + // > + // Try to uninstall LoadFile2 protocol if exists > + // > + Status =3D gBS->OpenProtocol ( > + Handle, > + &gEfiLoadFile2ProtocolGuid, > + NULL, > + gPciBusDriverBinding.DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_TEST_PROTOCOL > + ); > + if (!EFI_ERROR (Status)) { > + Status =3D gBS->UninstallMultipleProtocolInterfaces ( > + Handle, > + &gEfiLoadFile2ProtocolGuid, > + &PciIoDevice->LoadFile2, > + NULL > + ); > + } > + // > + // Restore Status > + // > + Status =3D EFI_SUCCESS; > + } > + > + > + if (EFI_ERROR (Status)) { > + gBS->OpenProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo, > + gPciBusDriverBinding.DriverBindingHandle, > + Handle, > + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER > + ); > + return Status; > + } > + > + // > + // The Device Driver should disable this device after disconnect > + // so the Pci Bus driver will not touch this device any more. > + // Restore the register field to the original value > + // > + PciIoDevice->Registered =3D FALSE; > + PciIoDevice->Handle =3D NULL; > + } else { > + > + // > + // Handle may be closed before > + // > + return EFI_SUCCESS; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Start to manage the PCI device on the specified root bridge or PCI-PCI > Bridge. > + > + @param Controller The root bridge handle. > + @param RootBridge A pointer to the PCI_IO_DEVICE. > + @param RemainingDevicePath A pointer to the > EFI_DEVICE_PATH_PROTOCOL. > + @param NumberOfChildren Children number. > + @param ChildHandleBuffer A pointer to the child handle buffer. > + > + @retval EFI_NOT_READY Device is not allocated. > + @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge. > + @retval EFI_NOT_FOUND Can not find the specific device. > + @retval EFI_SUCCESS Success to start Pci devices on bridge. > + > +**/ > +EFI_STATUS > +StartPciDevicesOnBridge ( > + IN EFI_HANDLE Controller, > + IN PCI_IO_DEVICE *RootBridge, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, > + IN OUT UINT8 *NumberOfChildren, > + IN OUT EFI_HANDLE *ChildHandleBuffer > + ) > + > +{ > + PCI_IO_DEVICE *PciIoDevice; > + EFI_DEV_PATH_PTR Node; > + EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; > + EFI_STATUS Status; > + LIST_ENTRY *CurrentLink; > + UINT64 Supports; > + > + PciIoDevice =3D NULL; > + CurrentLink =3D RootBridge->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &RootBridge->ChildLis= t) { > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + if (RemainingDevicePath !=3D NULL) { > + > + Node.DevPath =3D RemainingDevicePath; > + > + if (Node.Pci->Device !=3D PciIoDevice->DeviceNumber || > + Node.Pci->Function !=3D PciIoDevice->FunctionNumber) { > + CurrentLink =3D CurrentLink->ForwardLink; > + continue; > + } > + > + // > + // Check if the device has been assigned with required resource > + // > + if (!PciIoDevice->Allocated) { > + return EFI_NOT_READY; > + } > + > + // > + // Check if the current node has been registered before > + // If it is not, register it > + // > + if (!PciIoDevice->Registered) { > + Status =3D RegisterPciDevice ( > + Controller, > + PciIoDevice, > + NULL > + ); > + > + } > + > + if (NumberOfChildren !=3D NULL && ChildHandleBuffer !=3D NULL && > PciIoDevice->Registered) { > + ChildHandleBuffer[*NumberOfChildren] =3D PciIoDevice->Handle; > + (*NumberOfChildren)++; > + } > + > + // > + // Get the next device path > + // > + CurrentDevicePath =3D NextDevicePathNode (RemainingDevicePath); > + if (IsDevicePathEnd (CurrentDevicePath)) { > + return EFI_SUCCESS; > + } > + > + // > + // If it is a PPB > + // > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { > + Status =3D StartPciDevicesOnBridge ( > + Controller, > + PciIoDevice, > + CurrentDevicePath, > + NumberOfChildren, > + ChildHandleBuffer > + ); > + > + PciIoDevice->PciIo.Attributes ( > + &(PciIoDevice->PciIo), > + EfiPciIoAttributeOperationSupported, > + 0, > + &Supports > + ); > + Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; > + PciIoDevice->PciIo.Attributes ( > + &(PciIoDevice->PciIo), > + EfiPciIoAttributeOperationEnable, > + Supports, > + NULL > + ); > + > + return Status; > + } else { > + > + // > + // Currently, the PCI bus driver only support PCI-PCI bridge > + // > + return EFI_UNSUPPORTED; > + } > + > + } else { > + > + // > + // If remaining device path is NULL, > + // try to enable all the pci devices under this bridge > + // > + if (!PciIoDevice->Registered && PciIoDevice->Allocated) { > + Status =3D RegisterPciDevice ( > + Controller, > + PciIoDevice, > + NULL > + ); > + > + } > + > + if (NumberOfChildren !=3D NULL && ChildHandleBuffer !=3D NULL && > PciIoDevice->Registered) { > + ChildHandleBuffer[*NumberOfChildren] =3D PciIoDevice->Handle; > + (*NumberOfChildren)++; > + } > + > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { > + Status =3D StartPciDevicesOnBridge ( > + Controller, > + PciIoDevice, > + RemainingDevicePath, > + NumberOfChildren, > + ChildHandleBuffer > + ); > + > + PciIoDevice->PciIo.Attributes ( > + &(PciIoDevice->PciIo), > + EfiPciIoAttributeOperationSupported, > + 0, > + &Supports > + ); > + Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; > + PciIoDevice->PciIo.Attributes ( > + &(PciIoDevice->PciIo), > + EfiPciIoAttributeOperationEnable, > + Supports, > + NULL > + ); > + > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + } > + > + if (PciIoDevice =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } else { > + return EFI_SUCCESS; > + } > +} > + > +/** > + Start to manage all the PCI devices it found previously under > + the entire host bridge. > + > + @param Controller The root bridge handle. > + > + @retval EFI_NOT_READY Device is not allocated. > + @retval EFI_SUCCESS Success to start Pci device on host bridge. > + > +**/ > +EFI_STATUS > +StartPciDevices ( > + IN EFI_HANDLE Controller > + ) > +{ > + PCI_IO_DEVICE *RootBridge; > + EFI_HANDLE ThisHostBridge; > + LIST_ENTRY *CurrentLink; > + > + RootBridge =3D GetRootBridgeByHandle (Controller); > + ASSERT (RootBridge !=3D NULL); > + ThisHostBridge =3D RootBridge->PciRootBridgeIo->ParentHandle; > + > + CurrentLink =3D mPciDevicePool.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &mPciDevicePool) { > + > + RootBridge =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + // > + // Locate the right root bridge to start > + // > + if (RootBridge->PciRootBridgeIo->ParentHandle =3D=3D ThisHostBridge)= { > + StartPciDevicesOnBridge ( > + RootBridge->Handle, > + RootBridge, > + NULL, > + NULL, > + NULL > + ); > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Create root bridge device. > + > + @param RootBridgeHandle Specified root bridge handle. > + > + @return The crated root bridge device instance, NULL means no > + root bridge device instance created. > + > +**/ > +PCI_IO_DEVICE * > +CreateRootBridge ( > + IN EFI_HANDLE RootBridgeHandle > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *Dev; > + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + > + Dev =3D AllocateZeroPool (sizeof (PCI_IO_DEVICE)); > + if (Dev =3D=3D NULL) { > + return NULL; > + } > + > + Dev->Signature =3D PCI_IO_DEVICE_SIGNATURE; > + Dev->Handle =3D RootBridgeHandle; > + InitializeListHead (&Dev->ChildList); > + > + Status =3D gBS->OpenProtocol ( > + RootBridgeHandle, > + &gEfiDevicePathProtocolGuid, > + (VOID **) &ParentDevicePath, > + gPciBusDriverBinding.DriverBindingHandle, > + RootBridgeHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (EFI_ERROR (Status)) { > + FreePool (Dev); > + return NULL; > + } > + > + // > + // Record the root bridge parent device path > + // > + Dev->DevicePath =3D DuplicateDevicePath (ParentDevicePath); > + > + // > + // Get the pci root bridge io protocol > + // > + Status =3D gBS->OpenProtocol ( > + RootBridgeHandle, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo, > + gPciBusDriverBinding.DriverBindingHandle, > + RootBridgeHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (EFI_ERROR (Status)) { > + FreePciDevice (Dev); > + return NULL; > + } > + > + Dev->PciRootBridgeIo =3D PciRootBridgeIo; > + > + // > + // Initialize the PCI I/O instance structure > + // > + InitializePciIoInstance (Dev); > + InitializePciDriverOverrideInstance (Dev); > + InitializePciLoadFile2 (Dev); > + > + // > + // Initialize reserved resource list and > + // option rom driver list > + // > + InitializeListHead (&Dev->ReservedResourceList); > + InitializeListHead (&Dev->OptionRomDriverList); > + > + return Dev; > +} > + > +/** > + Get root bridge device instance by specific root bridge handle. > + > + @param RootBridgeHandle Given root bridge handle. > + > + @return The root bridge device instance, NULL means no root bridge > + device instance found. > + > +**/ > +PCI_IO_DEVICE * > +GetRootBridgeByHandle ( > + EFI_HANDLE RootBridgeHandle > + ) > +{ > + PCI_IO_DEVICE *RootBridgeDev; > + LIST_ENTRY *CurrentLink; > + > + CurrentLink =3D mPciDevicePool.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &mPciDevicePool) { > + > + RootBridgeDev =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + if (RootBridgeDev->Handle =3D=3D RootBridgeHandle) { > + return RootBridgeDev; > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return NULL; > +} > + > +/** > + Judge whether Pci device existed. > + > + @param Bridge Parent bridge instance. > + @param PciIoDevice Device instance. > + > + @retval TRUE Pci device existed. > + @retval FALSE Pci device did not exist. > + > +**/ > +BOOLEAN > +PciDeviceExisted ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + > + PCI_IO_DEVICE *Temp; > + LIST_ENTRY *CurrentLink; > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (Temp =3D=3D PciIoDevice) { > + return TRUE; > + } > + > + if (!IsListEmpty (&Temp->ChildList)) { > + if (PciDeviceExisted (Temp, PciIoDevice)) { > + return TRUE; > + } > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return FALSE; > +} > + > +/** > + Get the active VGA device on the specified Host Bridge. > + > + @param HostBridgeHandle Host Bridge handle. > + > + @return The active VGA device on the specified Host Bridge. > + > +**/ > +PCI_IO_DEVICE * > +LocateVgaDeviceOnHostBridge ( > + IN EFI_HANDLE HostBridgeHandle > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *PciIoDevice; > + > + CurrentLink =3D mPciDevicePool.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &mPciDevicePool) { > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (PciIoDevice->PciRootBridgeIo->ParentHandle=3D=3D HostBridgeHandl= e) { > + > + PciIoDevice =3D LocateVgaDevice (PciIoDevice); > + > + if (PciIoDevice !=3D NULL) { > + return PciIoDevice; > + } > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return NULL; > +} > + > +/** > + Locate the active VGA device under the bridge. > + > + @param Bridge PCI IO instance for the bridge. > + > + @return The active VGA device. > + > +**/ > +PCI_IO_DEVICE * > +LocateVgaDevice ( > + IN PCI_IO_DEVICE *Bridge > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *PciIoDevice; > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (IS_PCI_VGA(&PciIoDevice->Pci) && > + (PciIoDevice->Attributes & > + (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | > + EFI_PCI_IO_ATTRIBUTE_VGA_IO | > + EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) !=3D 0) { > + return PciIoDevice; > + } > + > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { > + > + PciIoDevice =3D LocateVgaDevice (PciIoDevice); > + > + if (PciIoDevice !=3D NULL) { > + return PciIoDevice; > + } > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return NULL; > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDeviceSupport.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDeviceSupport.h > new file mode 100644 > index 0000000000..acc0edc0bb > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDeviceSupport.h > @@ -0,0 +1,266 @@ > +/** @file > + Supporting functions declaration for PCI devices management. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_DEVICE_SUPPORT_H_ > +#define _EFI_PCI_DEVICE_SUPPORT_H_ > + > +/** > + Initialize the PCI devices pool. > + > +**/ > +VOID > +InitializePciDevicePool ( > + VOID > + ); > + > +/** > + Insert a root bridge into PCI device pool. > + > + @param RootBridge A pointer to the PCI_IO_DEVICE. > + > +**/ > +VOID > +InsertRootBridge ( > + IN PCI_IO_DEVICE *RootBridge > + ); > + > +/** > + This function is used to insert a PCI device node under > + a bridge. > + > + @param Bridge The PCI bridge. > + @param PciDeviceNode The PCI device needs inserting. > + > +**/ > +VOID > +InsertPciDevice ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_IO_DEVICE *PciDeviceNode > + ); > + > +/** > + Destroy root bridge and remove it from device tree. > + > + @param RootBridge The bridge want to be removed. > + > +**/ > +VOID > +DestroyRootBridge ( > + IN PCI_IO_DEVICE *RootBridge > + ); > + > +/** > + Destroy all the pci device node under the bridge. > + Bridge itself is not included. > + > + @param Bridge A pointer to the PCI_IO_DEVICE. > + > +**/ > +VOID > +DestroyPciDeviceTree ( > + IN PCI_IO_DEVICE *Bridge > + ); > + > +/** > + Destroy all device nodes under the root bridge > + specified by Controller. > + > + The root bridge itself is also included. > + > + @param Controller Root bridge handle. > + > + @retval EFI_SUCCESS Destroy all device nodes successfully. > + @retval EFI_NOT_FOUND Cannot find any PCI device under specified > + root bridge. > + > +**/ > +EFI_STATUS > +DestroyRootBridgeByHandle ( > + IN EFI_HANDLE Controller > + ); > + > +/** > + This function registers the PCI IO device. > + > + It creates a handle for this PCI IO device (if the handle does not exi= st), > attaches > + appropriate protocols onto the handle, does necessary initialization, = and > sets up > + parent/child relationship with its bus controller. > + > + @param Controller An EFI handle for the PCI bus controller. > + @param PciIoDevice A PCI_IO_DEVICE pointer to the PCI IO device to = be > registered. > + @param Handle A pointer to hold the returned EFI handle for th= e PCI > IO device. > + > + @retval EFI_SUCCESS The PCI device is successfully registered. > + @retval other An error occurred when registering the PCI devic= e. > + > +**/ > +EFI_STATUS > +RegisterPciDevice ( > + IN EFI_HANDLE Controller, > + IN PCI_IO_DEVICE *PciIoDevice, > + OUT EFI_HANDLE *Handle OPTIONAL > + ); > + > +/** > + This function is used to remove the whole PCI devices on the specified > bridge from > + the root bridge. > + > + @param RootBridgeHandle The root bridge device handle. > + @param Bridge The bridge device to be removed. > + > +**/ > +VOID > +RemoveAllPciDeviceOnBridge ( > + EFI_HANDLE RootBridgeHandle, > + PCI_IO_DEVICE *Bridge > + ); > + > +/** > + This function is used to de-register the PCI IO device. > + > + That includes un-installing PciIo protocol from the specified PCI > + device handle. > + > + @param Controller An EFI handle for the PCI bus controller. > + @param Handle PCI device handle. > + > + @retval EFI_SUCCESS The PCI device is successfully de-registered. > + @retval other An error occurred when de-registering the PCI dev= ice. > + > +**/ > +EFI_STATUS > +DeRegisterPciDevice ( > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE Handle > + ); > + > +/** > + Start to manage the PCI device on the specified root bridge or PCI-PCI > Bridge. > + > + @param Controller The root bridge handle. > + @param RootBridge A pointer to the PCI_IO_DEVICE. > + @param RemainingDevicePath A pointer to the > EFI_DEVICE_PATH_PROTOCOL. > + @param NumberOfChildren Children number. > + @param ChildHandleBuffer A pointer to the child handle buffer. > + > + @retval EFI_NOT_READY Device is not allocated. > + @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge. > + @retval EFI_NOT_FOUND Can not find the specific device. > + @retval EFI_SUCCESS Success to start Pci devices on bridge. > + > +**/ > +EFI_STATUS > +StartPciDevicesOnBridge ( > + IN EFI_HANDLE Controller, > + IN PCI_IO_DEVICE *RootBridge, > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, > + IN OUT UINT8 *NumberOfChildren, > + IN OUT EFI_HANDLE *ChildHandleBuffer > + ); > + > +/** > + Start to manage all the PCI devices it found previously under > + the entire host bridge. > + > + @param Controller The root bridge handle. > + > + @retval EFI_NOT_READY Device is not allocated. > + @retval EFI_SUCCESS Success to start Pci device on host bridge. > + > +**/ > +EFI_STATUS > +StartPciDevices ( > + IN EFI_HANDLE Controller > + ); > + > +/** > + Create root bridge device. > + > + @param RootBridgeHandle Specified root bridge handle. > + > + @return The crated root bridge device instance, NULL means no > + root bridge device instance created. > + > +**/ > +PCI_IO_DEVICE * > +CreateRootBridge ( > + IN EFI_HANDLE RootBridgeHandle > + ); > + > +/** > + Get root bridge device instance by specific root bridge handle. > + > + @param RootBridgeHandle Given root bridge handle. > + > + @return The root bridge device instance, NULL means no root bridge > + device instance found. > + > +**/ > +PCI_IO_DEVICE * > +GetRootBridgeByHandle ( > + EFI_HANDLE RootBridgeHandle > + ); > + > + > +/** > + Judge whether Pci device existed. > + > + @param Bridge Parent bridge instance. > + @param PciIoDevice Device instance. > + > + @retval TRUE Pci device existed. > + @retval FALSE Pci device did not exist. > + > +**/ > +BOOLEAN > +PciDeviceExisted ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Get the active VGA device on the specified Host Bridge. > + > + @param HostBridgeHandle Host Bridge handle. > + > + @return The active VGA device on the specified Host Bridge. > + > +**/ > +PCI_IO_DEVICE * > +LocateVgaDeviceOnHostBridge ( > + IN EFI_HANDLE HostBridgeHandle > + ); > + > +/** > + Locate the active VGA device under the bridge. > + > + @param Bridge PCI IO instance for the bridge. > + > + @return The active VGA device. > + > +**/ > +PCI_IO_DEVICE * > +LocateVgaDevice ( > + IN PCI_IO_DEVICE *Bridge > + ); > + > + > +/** > + Destroy a pci device node. > + > + All direct or indirect allocated resource for this node will be freed. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE to be destroyed. > + > +**/ > +VOID > +FreePciDevice ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDriverOverride.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDriverOverride.c > new file mode 100644 > index 0000000000..0c3f684c8c > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDriverOverride.c > @@ -0,0 +1,188 @@ > +/** @file > + Functions implementation for Bus Specific Driver Override protocol. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +/** > + Initializes a PCI Driver Override Instance. > + > + @param PciIoDevice PCI Device instance. > + > +**/ > +VOID > +InitializePciDriverOverrideInstance ( > + IN OUT PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + PciIoDevice->PciDriverOverride.GetDriver =3D GetDriver; > +} > + > +/** > + Find the image handle whose path equals to ImagePath. > + > + @param ImagePath Image path. > + > + @return Image handle. > +**/ > +EFI_HANDLE > +LocateImageHandle ( > + IN EFI_DEVICE_PATH_PROTOCOL *ImagePath > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE *Handles; > + UINTN Index; > + UINTN HandleNum; > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > + UINTN ImagePathSize; > + EFI_HANDLE ImageHandle; > + > + Status =3D gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiLoadedImageDevicePathProtocolGuid, > + NULL, > + &HandleNum, > + &Handles > + ); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + > + ImageHandle =3D NULL; > + ImagePathSize =3D GetDevicePathSize (ImagePath); > + > + for (Index =3D 0; Index < HandleNum; Index++) { > + Status =3D gBS->HandleProtocol (Handles[Index], > &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &DevicePath); > + if (EFI_ERROR (Status)) { > + continue; > + } > + if ((ImagePathSize =3D=3D GetDevicePathSize (DevicePath)) && > + (CompareMem (ImagePath, DevicePath, ImagePathSize) =3D=3D 0) > + ) { > + ImageHandle =3D Handles[Index]; > + break; > + } > + } > + > + FreePool (Handles); > + return ImageHandle; > +} > + > +/** > + Uses a bus specific algorithm to retrieve a driver image handle for a > controller. > + > + @param This A pointer to the > EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance. > + @param DriverImageHandle On input, a pointer to the previous driv= er > image handle returned > + by GetDriver(). On output, a pointer to = the next driver > + image handle. Passing in a NULL, will re= turn the first driver > + image handle. > + > + @retval EFI_SUCCESS A bus specific override driver is return= ed in > DriverImageHandle. > + @retval EFI_NOT_FOUND The end of the list of override drivers = was > reached. > + A bus specific override driver is not re= turned in > DriverImageHandle. > + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that > was returned on a > + previous call to GetDriver(). > + > +**/ > +EFI_STATUS > +EFIAPI > +GetDriver ( > + IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This, > + IN OUT EFI_HANDLE *DriverImage= Handle > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + LIST_ENTRY *Link; > + PCI_DRIVER_OVERRIDE_LIST *Override; > + BOOLEAN ReturnNext; > + > + Override =3D NULL; > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This); > + ReturnNext =3D (BOOLEAN) (*DriverImageHandle =3D=3D NULL); > + for ( Link =3D GetFirstNode (&PciIoDevice->OptionRomDriverList) > + ; !IsNull (&PciIoDevice->OptionRomDriverList, Link) > + ; Link =3D GetNextNode (&PciIoDevice->OptionRomDriverList, Link) > + ) { > + > + Override =3D DRIVER_OVERRIDE_FROM_LINK (Link); > + > + if (ReturnNext) { > + if (Override->DriverImageHandle =3D=3D NULL) { > + Override->DriverImageHandle =3D LocateImageHandle (Override- > >DriverImagePath); > + } > + > + if (Override->DriverImageHandle =3D=3D NULL) { > + // > + // The Option ROM identified by Override->DriverImagePath is not > loaded. > + // > + continue; > + } else { > + *DriverImageHandle =3D Override->DriverImageHandle; > + return EFI_SUCCESS; > + } > + } > + > + if (*DriverImageHandle =3D=3D Override->DriverImageHandle) { > + ReturnNext =3D TRUE; > + } > + } > + > + ASSERT (IsNull (&PciIoDevice->OptionRomDriverList, Link)); > + // > + // ReturnNext indicates a handle match happens. > + // If all nodes are checked without handle match happening, > + // the DriverImageHandle should be a invalid handle. > + // > + if (ReturnNext) { > + return EFI_NOT_FOUND; > + } else { > + return EFI_INVALID_PARAMETER; > + } > +} > + > +/** > + Add an overriding driver image. > + > + @param PciIoDevice Instance of PciIo device. > + @param DriverImageHandle Image handle of newly added driver image. > + @param DriverImagePath Device path of newly added driver image. > + > + @retval EFI_SUCCESS Successfully added driver. > + @retval EFI_OUT_OF_RESOURCES No memory resource for new driver > instance. > + @retval other Some error occurred when locating > gEfiLoadedImageProtocolGuid. > + > +**/ > +EFI_STATUS > +AddDriver ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN EFI_HANDLE DriverImageHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath > + ) > +{ > + PCI_DRIVER_OVERRIDE_LIST *Node; > + > + // > + // Caller should pass in either Image Handle or Image Path, but not bo= th. > + // > + ASSERT ((DriverImageHandle =3D=3D NULL) || (DriverImagePath =3D=3D NUL= L)); > + > + Node =3D AllocateZeroPool (sizeof (PCI_DRIVER_OVERRIDE_LIST)); > + if (Node =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Node->Signature =3D DRIVER_OVERRIDE_SIGNATURE; > + Node->DriverImageHandle =3D DriverImageHandle; > + Node->DriverImagePath =3D DuplicateDevicePath (DriverImagePath); > + > + InsertTailList (&PciIoDevice->OptionRomDriverList, &Node->Link); > + > + PciIoDevice->BusOverride =3D TRUE; > + return EFI_SUCCESS; > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDriverOverride.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDriverOverride.h > new file mode 100644 > index 0000000000..ab058fa762 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciDriverOverride.h > @@ -0,0 +1,83 @@ > +/** @file > + Functions declaration for Bus Specific Driver Override protocol. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > + > +#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H_ > +#define _EFI_PCI_DRIVER_OVERRRIDE_H_ > + > +#define DRIVER_OVERRIDE_SIGNATURE SIGNATURE_32 ('d', 'r', 'o', 'v') > + > +// > +// PCI driver override driver image list > +// > +typedef struct { > + UINT32 Signature; > + LIST_ENTRY Link; > + EFI_HANDLE DriverImageHandle; > + EFI_DEVICE_PATH_PROTOCOL *DriverImagePath; > +} PCI_DRIVER_OVERRIDE_LIST; > + > + > +#define DRIVER_OVERRIDE_FROM_LINK(a) \ > + CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE) > + > +/** > + Initializes a PCI Driver Override Instance. > + > + @param PciIoDevice PCI Device instance. > + > +**/ > +VOID > +InitializePciDriverOverrideInstance ( > + IN OUT PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Add an overriding driver image. > + > + @param PciIoDevice Instance of PciIo device. > + @param DriverImageHandle Image handle of newly added driver image. > + @param DriverImagePath Device path of newly added driver image. > + > + @retval EFI_SUCCESS Successfully added driver. > + @retval EFI_OUT_OF_RESOURCES No memory resource for new driver > instance. > + @retval other Some error occurred when locating > gEfiLoadedImageProtocolGuid. > + > +**/ > +EFI_STATUS > +AddDriver ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN EFI_HANDLE DriverImageHandle, > + IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath > + ); > + > + > +/** > + Uses a bus specific algorithm to retrieve a driver image handle for a > controller. > + > + @param This A pointer to the > EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance. > + @param DriverImageHandle On input, a pointer to the previous driv= er > image handle returned > + by GetDriver(). On output, a pointer to = the next driver > + image handle. Passing in a NULL, will re= turn the first driver > + image handle. > + > + @retval EFI_SUCCESS A bus specific override driver is return= ed in > DriverImageHandle. > + @retval EFI_NOT_FOUND The end of the list of override drivers = was > reached. > + A bus specific override driver is not re= turned in > DriverImageHandle. > + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that > was returned on a > + previous call to GetDriver(). > + > +**/ > +EFI_STATUS > +EFIAPI > +GetDriver ( > + IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This, > + IN OUT EFI_HANDLE *DriverImage= Handle > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumerator.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumerator.c > new file mode 100644 > index 0000000000..4e1c328b7e > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumerator.c > @@ -0,0 +1,2210 @@ > +/** @file > + PCI eunmeration implementation on entire PCI bus system for PCI Bus > module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +(C) Copyright 2015 Hewlett Packard Enterprise Development LP
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +/** > + This routine is used to enumerate entire pci bus system > + in a given platform. > + > + @param Controller Parent controller handle. > + @param HostBridgeHandle Host bridge handle. > + > + @retval EFI_SUCCESS PCI enumeration finished successfully. > + @retval other Some error occurred when enumerating the pci bu= s > system. > + > +**/ > +EFI_STATUS > +PciEnumerator ( > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE HostBridgeHandle > + ) > +{ > + EFI_STATUS Status; > + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc; > + > + // > + // Get the pci host bridge resource allocation protocol > + // > + Status =3D gBS->OpenProtocol ( > + HostBridgeHandle, > + &gEfiPciHostBridgeResourceAllocationProtocolGuid, > + (VOID **) &PciResAlloc, > + gPciBusDriverBinding.DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Notify the pci bus enumeration is about to begin > + // > + Status =3D NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration)= ; > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Start the bus allocation phase > + // > + Status =3D PciHostBridgeEnumerator (PciResAlloc); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Submit the resource request > + // > + Status =3D PciHostBridgeResourceAllocator (PciResAlloc); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Notify the pci bus enumeration is about to complete > + // > + Status =3D NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Process P2C > + // > + Status =3D PciHostBridgeP2CProcess (PciResAlloc); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Process attributes for devices on this host bridge > + // > + Status =3D PciHostBridgeDeviceAttribute (PciResAlloc); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Enumerate PCI root bridge. > + > + @param PciResAlloc Pointer to protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + @param RootBridgeDev Instance of root bridge device. > + > + @retval EFI_SUCCESS Successfully enumerated root bridge. > + @retval other Failed to enumerate root bridge. > + > +**/ > +EFI_STATUS > +PciRootBridgeEnumerator ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc, > + IN PCI_IO_DEVICE *RootBridgeDev > + ) > +{ > + EFI_STATUS Status; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3; > + UINT8 SubBusNumber; > + UINT8 StartBusNumber; > + UINT8 PaddedBusRange; > + EFI_HANDLE RootBridgeHandle; > + UINT8 Desc; > + UINT64 AddrLen; > + UINT64 AddrRangeMin; > + > + SubBusNumber =3D 0; > + StartBusNumber =3D 0; > + PaddedBusRange =3D 0; > + > + // > + // Get the root bridge handle > + // > + RootBridgeHandle =3D RootBridgeDev->Handle; > + > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_PROGRESS_CODE, > + EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM, > + RootBridgeDev->DevicePath > + ); > + > + // > + // Get the Bus information > + // > + Status =3D PciResAlloc->StartBusEnumeration ( > + PciResAlloc, > + RootBridgeHandle, > + (VOID **) &Configuration > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (Configuration =3D=3D NULL || Configuration->Desc =3D=3D > ACPI_END_TAG_DESCRIPTOR) { > + return EFI_INVALID_PARAMETER; > + } > + RootBridgeDev->BusNumberRanges =3D Configuration; > + > + // > + // Sort the descriptors in ascending order > + // > + for (Configuration1 =3D Configuration; Configuration1->Desc !=3D > ACPI_END_TAG_DESCRIPTOR; Configuration1++) { > + Configuration2 =3D Configuration1; > + for (Configuration3 =3D Configuration1 + 1; Configuration3->Desc != =3D > ACPI_END_TAG_DESCRIPTOR; Configuration3++) { > + if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) { > + Configuration2 =3D Configuration3; > + } > + } > + // > + // All other fields other than AddrRangeMin and AddrLen are ignored = in a > descriptor, > + // so only need to swap these two fields. > + // > + if (Configuration2 !=3D Configuration1) { > + AddrRangeMin =3D Configuration1->AddrRangeMin; > + Configuration1->AddrRangeMin =3D Configuration2->AddrRangeMin; > + Configuration2->AddrRangeMin =3D AddrRangeMin; > + > + AddrLen =3D Configuration1->AddrLen; > + Configuration1->AddrLen =3D Configuration2->AddrLen; > + Configuration2->AddrLen =3D AddrLen; > + } > + } > + > + // > + // Get the bus number to start with > + // > + StartBusNumber =3D (UINT8) (Configuration->AddrRangeMin); > + > + // > + // Initialize the subordinate bus number > + // > + SubBusNumber =3D StartBusNumber; > + > + // > + // Reset all assigned PCI bus number > + // > + ResetAllPpbBusNumber ( > + RootBridgeDev, > + StartBusNumber > + ); > + > + // > + // Assign bus number > + // > + Status =3D PciScanBus ( > + RootBridgeDev, > + StartBusNumber, > + &SubBusNumber, > + &PaddedBusRange > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + > + // > + // Assign max bus number scanned > + // > + > + Status =3D PciAllocateBusNumber (RootBridgeDev, SubBusNumber, > PaddedBusRange, &SubBusNumber); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Find the bus range which contains the higest bus number, then retur= ns > the number of buses > + // that should be decoded. > + // > + while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < > SubBusNumber) { > + Configuration++; > + } > + AddrLen =3D Configuration->AddrLen; > + Configuration->AddrLen =3D SubBusNumber - Configuration- > >AddrRangeMin + 1; > + > + // > + // Save the Desc field of the next descriptor. Mark the next descripto= r as > an END descriptor. > + // > + Configuration++; > + Desc =3D Configuration->Desc; > + Configuration->Desc =3D ACPI_END_TAG_DESCRIPTOR; > + > + // > + // Set bus number > + // > + Status =3D PciResAlloc->SetBusNumbers ( > + PciResAlloc, > + RootBridgeHandle, > + RootBridgeDev->BusNumberRanges > + ); > + > + // > + // Restore changed fields > + // > + Configuration->Desc =3D Desc; > + (Configuration - 1)->AddrLen =3D AddrLen; > + > + return Status; > +} > + > +/** > + This routine is used to process all PCI devices' Option Rom > + on a certain root bridge. > + > + @param Bridge Given parent's root bridge. > + @param RomBase Base address of ROM driver loaded from. > + @param MaxLength Maximum rom size. > + > +**/ > +VOID > +ProcessOptionRom ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT64 RomBase, > + IN UINT64 MaxLength > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *Temp; > + > + // > + // Go through bridges to reach all devices > + // > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + if (!IsListEmpty (&Temp->ChildList)) { > + > + // > + // Go further to process the option rom under this bridge > + // > + ProcessOptionRom (Temp, RomBase, MaxLength); > + } > + > + if (Temp->RomSize !=3D 0 && Temp->RomSize <=3D MaxLength) { > + > + // > + // Load and process the option rom > + // > + LoadOpRomImage (Temp, RomBase); > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > +} > + > +/** > + This routine is used to assign bus number to the given PCI bus system > + > + @param Bridge Parent root bridge instance. > + @param StartBusNumber Number of beginning. > + @param SubBusNumber The number of sub bus. > + > + @retval EFI_SUCCESS Successfully assigned bus number. > + @retval EFI_DEVICE_ERROR Failed to assign bus number. > + > +**/ > +EFI_STATUS > +PciAssignBusNumber ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber, > + OUT UINT8 *SubBusNumber > + ) > +{ > + EFI_STATUS Status; > + PCI_TYPE00 Pci; > + UINT8 Device; > + UINT8 Func; > + UINT64 Address; > + UINTN SecondBus; > + UINT16 Register; > + UINT8 Register8; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + > + PciRootBridgeIo =3D Bridge->PciRootBridgeIo; > + > + SecondBus =3D 0; > + Register =3D 0; > + > + *SubBusNumber =3D StartBusNumber; > + > + // > + // First check to see whether the parent is ppb > + // > + for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) { > + for (Func =3D 0; Func <=3D PCI_MAX_FUNC; Func++) { > + > + // > + // Check to see whether a pci device is present > + // > + Status =3D PciDevicePresent ( > + PciRootBridgeIo, > + &Pci, > + StartBusNumber, > + Device, > + Func > + ); > + > + if (EFI_ERROR (Status) && Func =3D=3D 0) { > + // > + // go to next device if there is no Function 0 > + // > + break; > + } > + > + if (!EFI_ERROR (Status) && > + (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) { > + > + // > + // Reserved one bus for cardbus bridge > + // > + Status =3D PciAllocateBusNumber (Bridge, *SubBusNumber, 1, > SubBusNumber); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + SecondBus =3D *SubBusNumber; > + > + Register =3D (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumb= er); > + > + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1= 8); > + > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint16, > + Address, > + 1, > + &Register > + ); > + > + // > + // Initialize SubBusNumber to SecondBus > + // > + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A)= ; > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint8, > + Address, > + 1, > + SubBusNumber > + ); > + // > + // If it is PPB, resursively search down this bridge > + // > + if (IS_PCI_BRIDGE (&Pci)) { > + > + Register8 =3D 0xFF; > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint8, > + Address, > + 1, > + &Register8 > + ); > + > + Status =3D PciAssignBusNumber ( > + Bridge, > + (UINT8) (SecondBus), > + SubBusNumber > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + } > + > + // > + // Set the current maximum bus number under the PPB > + // > + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A)= ; > + > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint8, > + Address, > + 1, > + SubBusNumber > + ); > + > + } > + > + if (Func =3D=3D 0 && !IS_PCI_MULTI_FUNC (&Pci)) { > + > + // > + // Skip sub functions, this is not a multi function device > + // > + Func =3D PCI_MAX_FUNC; > + } > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This routine is used to determine the root bridge attribute by interfa= cing > + the host bridge resource allocation protocol. > + > + @param PciResAlloc Protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > + @param RootBridgeDev Root bridge instance > + > + @retval EFI_SUCCESS Successfully got root bridge's attribute. > + @retval other Failed to get attribute. > + > +**/ > +EFI_STATUS > +DetermineRootBridgeAttributes ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc, > + IN PCI_IO_DEVICE *RootBridgeDev > + ) > +{ > + UINT64 Attributes; > + EFI_STATUS Status; > + EFI_HANDLE RootBridgeHandle; > + > + Attributes =3D 0; > + RootBridgeHandle =3D RootBridgeDev->Handle; > + > + // > + // Get root bridge attribute by calling into pci host bridge resource > allocation protocol > + // > + Status =3D PciResAlloc->GetAllocAttributes ( > + PciResAlloc, > + RootBridgeHandle, > + &Attributes > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Here is the point where PCI bus driver calls HOST bridge allocation > protocol > + // Currently we hardcoded for ea815 > + // > + if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) !=3D 0) { > + RootBridgeDev->Decodes |=3D > EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED; > + } > + > + if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) !=3D 0) { > + RootBridgeDev->Decodes |=3D EFI_BRIDGE_MEM64_DECODE_SUPPORTED; > + RootBridgeDev->Decodes |=3D > EFI_BRIDGE_PMEM64_DECODE_SUPPORTED; > + } > + > + RootBridgeDev->Decodes |=3D EFI_BRIDGE_MEM32_DECODE_SUPPORTED; > + RootBridgeDev->Decodes |=3D > EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; > + RootBridgeDev->Decodes |=3D EFI_BRIDGE_IO16_DECODE_SUPPORTED; > + > + return EFI_SUCCESS; > +} > + > +/** > + Get Max Option Rom size on specified bridge. > + > + @param Bridge Given bridge device instance. > + > + @return Max size of option rom needed. > + > +**/ > +UINT32 > +GetMaxOptionRomSize ( > + IN PCI_IO_DEVICE *Bridge > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *Temp; > + UINT32 MaxOptionRomSize; > + UINT32 TempOptionRomSize; > + > + MaxOptionRomSize =3D 0; > + > + // > + // Go through bridges to reach all devices > + // > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + if (!IsListEmpty (&Temp->ChildList)) { > + > + // > + // Get max option rom size under this bridge > + // > + TempOptionRomSize =3D GetMaxOptionRomSize (Temp); > + > + // > + // Compare with the option rom size of the bridge > + // Get the larger one > + // > + if (Temp->RomSize > TempOptionRomSize) { > + TempOptionRomSize =3D Temp->RomSize; > + } > + > + } else { > + > + // > + // For devices get the rom size directly > + // > + TempOptionRomSize =3D Temp->RomSize; > + } > + > + // > + // Get the largest rom size on this bridge > + // > + if (TempOptionRomSize > MaxOptionRomSize) { > + MaxOptionRomSize =3D TempOptionRomSize; > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return MaxOptionRomSize; > +} > + > +/** > + Process attributes of devices on this host bridge > + > + @param PciResAlloc Protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + > + @retval EFI_SUCCESS Successfully process attribute. > + @retval EFI_NOT_FOUND Can not find the specific root bridge device. > + @retval other Failed to determine the root bridge device's att= ribute. > + > +**/ > +EFI_STATUS > +PciHostBridgeDeviceAttribute ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ) > +{ > + EFI_HANDLE RootBridgeHandle; > + PCI_IO_DEVICE *RootBridgeDev; > + EFI_STATUS Status; > + > + RootBridgeHandle =3D NULL; > + > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) > =3D=3D EFI_SUCCESS) { > + > + // > + // Get RootBridg Device by handle > + // > + RootBridgeDev =3D GetRootBridgeByHandle (RootBridgeHandle); > + > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Set the attributes for devcies behind the Root Bridge > + // > + Status =3D DetermineDeviceAttribute (RootBridgeDev); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Get resource allocation status from the ACPI resource descriptor. > + > + @param AcpiConfig Point to Acpi configuration table. > + @param IoResStatus Return the status of I/O resource. > + @param Mem32ResStatus Return the status of 32-bit Memory resource. > + @param PMem32ResStatus Return the status of 32-bit Prefetchable > Memory resource. > + @param Mem64ResStatus Return the status of 64-bit Memory resource. > + @param PMem64ResStatus Return the status of 64-bit Prefetchable > Memory resource. > + > +**/ > +VOID > +GetResourceAllocationStatus ( > + VOID *AcpiConfig, > + OUT UINT64 *IoResStatus, > + OUT UINT64 *Mem32ResStatus, > + OUT UINT64 *PMem32ResStatus, > + OUT UINT64 *Mem64ResStatus, > + OUT UINT64 *PMem64ResStatus > + ) > +{ > + UINT8 *Temp; > + UINT64 ResStatus; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc; > + > + Temp =3D (UINT8 *) AcpiConfig; > + > + while (*Temp =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR) { > + > + ACPIAddressDesc =3D (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) > Temp; > + ResStatus =3D ACPIAddressDesc->AddrTranslationOffset; > + > + switch (ACPIAddressDesc->ResType) { > + case 0: > + if (ACPIAddressDesc->AddrSpaceGranularity =3D=3D 32) { > + if (ACPIAddressDesc->SpecificFlag =3D=3D 0x06) { > + // > + // Pmem32 > + // > + *PMem32ResStatus =3D ResStatus; > + } else { > + // > + // Mem32 > + // > + *Mem32ResStatus =3D ResStatus; > + } > + } > + > + if (ACPIAddressDesc->AddrSpaceGranularity =3D=3D 64) { > + if (ACPIAddressDesc->SpecificFlag =3D=3D 0x06) { > + // > + // PMem64 > + // > + *PMem64ResStatus =3D ResStatus; > + } else { > + // > + // Mem64 > + // > + *Mem64ResStatus =3D ResStatus; > + } > + } > + > + break; > + > + case 1: > + // > + // Io > + // > + *IoResStatus =3D ResStatus; > + break; > + > + default: > + break; > + } > + > + Temp +=3D sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); > + } > +} > + > +/** > + Remove a PCI device from device pool and mark its bar. > + > + @param PciDevice Instance of Pci device. > + > + @retval EFI_SUCCESS Successfully remove the PCI device. > + @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge. > + > +**/ > +EFI_STATUS > +RejectPciDevice ( > + IN PCI_IO_DEVICE *PciDevice > + ) > +{ > + PCI_IO_DEVICE *Bridge; > + PCI_IO_DEVICE *Temp; > + LIST_ENTRY *CurrentLink; > + > + // > + // Remove the padding resource from a bridge > + // > + if ( IS_PCI_BRIDGE(&PciDevice->Pci) && > + PciDevice->ResourcePaddingDescriptors !=3D NULL ) { > + FreePool (PciDevice->ResourcePaddingDescriptors); > + PciDevice->ResourcePaddingDescriptors =3D NULL; > + return EFI_SUCCESS; > + } > + > + // > + // Skip RB and PPB > + // > + if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent =3D=3D NULL)= ) { > + return EFI_ABORTED; > + } > + > + if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) { > + // > + // Get the root bridge device > + // > + Bridge =3D PciDevice; > + while (Bridge->Parent !=3D NULL) { > + Bridge =3D Bridge->Parent; > + } > + > + RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice); > + > + // > + // Mark its bar > + // > + InitializeP2C (PciDevice); > + } > + > + // > + // Remove the device > + // > + Bridge =3D PciDevice->Parent; > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + if (Temp =3D=3D PciDevice) { > + InitializePciDevice (Temp); > + RemoveEntryList (CurrentLink); > + return EFI_SUCCESS; > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return EFI_ABORTED; > +} > + > +/** > + Determine whethter a PCI device can be rejected. > + > + @param PciResNode Pointer to Pci resource node instance. > + > + @retval TRUE The PCI device can be rejected. > + @retval TRUE The PCI device cannot be rejected. > + > +**/ > +BOOLEAN > +IsRejectiveDevice ( > + IN PCI_RESOURCE_NODE *PciResNode > + ) > +{ > + PCI_IO_DEVICE *Temp; > + > + Temp =3D PciResNode->PciDev; > + > + // > + // Ensure the device is present > + // > + if (Temp =3D=3D NULL) { > + return FALSE; > + } > + > + // > + // PPB and RB should go ahead > + // > + if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent =3D=3D NULL)) { > + return TRUE; > + } > + > + // > + // Skip device on Bus0 > + // > + if ((Temp->Parent !=3D NULL) && (Temp->BusNumber =3D=3D 0)) { > + return FALSE; > + } > + > + // > + // Skip VGA > + // > + if (IS_PCI_VGA (&Temp->Pci)) { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + Compare two resource nodes and get the larger resource consumer. > + > + @param PciResNode1 resource node 1 want to be compared > + @param PciResNode2 resource node 2 want to be compared > + > + @return Larger resource node. > + > +**/ > +PCI_RESOURCE_NODE * > +GetLargerConsumerDevice ( > + IN PCI_RESOURCE_NODE *PciResNode1, > + IN PCI_RESOURCE_NODE *PciResNode2 > + ) > +{ > + if (PciResNode2 =3D=3D NULL) { > + return PciResNode1; > + } > + > + if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2- > >PciDev->Parent =3D=3D NULL)) \ > + && (PciResNode2->ResourceUsage !=3D PciResUsagePadding) ) > + { > + return PciResNode1; > + } > + > + if (PciResNode1 =3D=3D NULL) { > + return PciResNode2; > + } > + > + if ((PciResNode1->Length) > (PciResNode2->Length)) { > + return PciResNode1; > + } > + > + return PciResNode2; > +} > + > + > +/** > + Get the max resource consumer in the host resource pool. > + > + @param ResPool Pointer to resource pool node. > + > + @return The max resource consumer in the host resource pool. > + > +**/ > +PCI_RESOURCE_NODE * > +GetMaxResourceConsumerDevice ( > + IN PCI_RESOURCE_NODE *ResPool > + ) > +{ > + PCI_RESOURCE_NODE *Temp; > + LIST_ENTRY *CurrentLink; > + PCI_RESOURCE_NODE *PciResNode; > + PCI_RESOURCE_NODE *PPBResNode; > + > + PciResNode =3D NULL; > + > + CurrentLink =3D ResPool->ChildList.ForwardLink; > + while (CurrentLink !=3D NULL && CurrentLink !=3D &ResPool->ChildList) = { > + > + Temp =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + > + if (!IsRejectiveDevice (Temp)) { > + CurrentLink =3D CurrentLink->ForwardLink; > + continue; > + } > + > + if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent > =3D=3D NULL)) \ > + && (Temp->ResourceUsage !=3D PciResUsagePadding)) > + { > + PPBResNode =3D GetMaxResourceConsumerDevice (Temp); > + PciResNode =3D GetLargerConsumerDevice (PciResNode, PPBResNode); > + } else { > + PciResNode =3D GetLargerConsumerDevice (PciResNode, Temp); > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return PciResNode; > +} > + > +/** > + Adjust host bridge allocation so as to reduce resource requirement > + > + @param IoPool Pointer to instance of I/O resource Node. > + @param Mem32Pool Pointer to instance of 32-bit memory resource > Node. > + @param PMem32Pool Pointer to instance of 32-bit Prefetchable > memory resource node. > + @param Mem64Pool Pointer to instance of 64-bit memory resource > node. > + @param PMem64Pool Pointer to instance of 64-bit Prefetchable > memory resource node. > + @param IoResStatus Status of I/O resource Node. > + @param Mem32ResStatus Status of 32-bit memory resource Node. > + @param PMem32ResStatus Status of 32-bit Prefetchable memory > resource node. > + @param Mem64ResStatus Status of 64-bit memory resource node. > + @param PMem64ResStatus Status of 64-bit Prefetchable memory > resource node. > + > + @retval EFI_SUCCESS Successfully adjusted resource on host bridge. > + @retval EFI_ABORTED Host bridge hasn't this resource type or no > resource be adjusted. > + > +**/ > +EFI_STATUS > +PciHostBridgeAdjustAllocation ( > + IN PCI_RESOURCE_NODE *IoPool, > + IN PCI_RESOURCE_NODE *Mem32Pool, > + IN PCI_RESOURCE_NODE *PMem32Pool, > + IN PCI_RESOURCE_NODE *Mem64Pool, > + IN PCI_RESOURCE_NODE *PMem64Pool, > + IN UINT64 IoResStatus, > + IN UINT64 Mem32ResStatus, > + IN UINT64 PMem32ResStatus, > + IN UINT64 Mem64ResStatus, > + IN UINT64 PMem64ResStatus > + ) > +{ > + BOOLEAN AllocationAjusted; > + PCI_RESOURCE_NODE *PciResNode; > + PCI_RESOURCE_NODE *ResPool[5]; > + PCI_IO_DEVICE *RemovedPciDev[5]; > + UINT64 ResStatus[5]; > + UINTN RemovedPciDevNum; > + UINTN DevIndex; > + UINTN ResType; > + EFI_STATUS Status; > + EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD > AllocFailExtendedData; > + > + PciResNode =3D NULL; > + ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *)); > + RemovedPciDevNum =3D 0; > + > + ResPool[0] =3D IoPool; > + ResPool[1] =3D Mem32Pool; > + ResPool[2] =3D PMem32Pool; > + ResPool[3] =3D Mem64Pool; > + ResPool[4] =3D PMem64Pool; > + > + ResStatus[0] =3D IoResStatus; > + ResStatus[1] =3D Mem32ResStatus; > + ResStatus[2] =3D PMem32ResStatus; > + ResStatus[3] =3D Mem64ResStatus; > + ResStatus[4] =3D PMem64ResStatus; > + > + AllocationAjusted =3D FALSE; > + > + for (ResType =3D 0; ResType < 5; ResType++) { > + > + if (ResStatus[ResType] =3D=3D EFI_RESOURCE_SATISFIED) { > + continue; > + } > + > + if (ResStatus[ResType] =3D=3D EFI_RESOURCE_NOT_SATISFIED) { > + // > + // Host bridge hasn't this resource type > + // > + return EFI_ABORTED; > + } > + > + // > + // Hostbridge hasn't enough resource > + // > + PciResNode =3D GetMaxResourceConsumerDevice (ResPool[ResType]); > + if (PciResNode =3D=3D NULL) { > + continue; > + } > + > + // > + // Check if the device has been removed before > + // > + for (DevIndex =3D 0; DevIndex < RemovedPciDevNum; DevIndex++) { > + if (PciResNode->PciDev =3D=3D RemovedPciDev[DevIndex]) { > + break; > + } > + } > + > + if (DevIndex !=3D RemovedPciDevNum) { > + continue; > + } > + > + // > + // Remove the device if it isn't in the array > + // > + Status =3D RejectPciDevice (PciResNode->PciDev); > + if (Status =3D=3D EFI_SUCCESS) { > + DEBUG (( > + EFI_D_ERROR, > + "PciBus: [%02x|%02x|%02x] was rejected due to resource > confliction.\n", > + PciResNode->PciDev->BusNumber, PciResNode->PciDev- > >DeviceNumber, PciResNode->PciDev->FunctionNumber > + )); > + > + // > + // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code > + // > + // > + // Have no way to get ReqRes, AllocRes & Bar here > + // > + ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData)); > + AllocFailExtendedData.DevicePathSize =3D (UINT16) sizeof > (EFI_DEVICE_PATH_PROTOCOL); > + AllocFailExtendedData.DevicePath =3D (UINT8 *) PciResNode->Pci= Dev- > >DevicePath; > + AllocFailExtendedData.Bar =3D PciResNode->Bar; > + > + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( > + EFI_PROGRESS_CODE, > + EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT, > + (VOID *) &AllocFailExtendedData, > + sizeof (AllocFailExtendedData) > + ); > + > + // > + // Add it to the array and indicate at least a device has been rej= ected > + // > + RemovedPciDev[RemovedPciDevNum++] =3D PciResNode->PciDev; > + AllocationAjusted =3D TRUE; > + } > + } > + // > + // End for > + // > + > + if (AllocationAjusted) { > + return EFI_SUCCESS; > + } else { > + return EFI_ABORTED; > + } > +} > + > +/** > + Summary requests for all resource type, and construct ACPI resource > + requestor instance. > + > + @param Bridge detecting bridge > + @param IoNode Pointer to instance of I/O resource Node > + @param Mem32Node Pointer to instance of 32-bit memory resource > Node > + @param PMem32Node Pointer to instance of 32-bit Pmemory resource > node > + @param Mem64Node Pointer to instance of 64-bit memory resource > node > + @param PMem64Node Pointer to instance of 64-bit Pmemory resource > node > + @param Config Output buffer holding new constructed APCI res= ource > requestor > + > + @retval EFI_SUCCESS Successfully constructed ACPI resource. > + @retval EFI_OUT_OF_RESOURCES No memory available. > + > +**/ > +EFI_STATUS > +ConstructAcpiResourceRequestor ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node, > + OUT VOID **Config > + ) > +{ > + UINT8 NumConfig; > + UINT8 Aperture; > + UINT8 *Configuration; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; > + EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd; > + > + NumConfig =3D 0; > + Aperture =3D 0; > + > + *Config =3D NULL; > + > + // > + // if there is io request, add to the io aperture > + // > + if (ResourceRequestExisted (IoNode)) { > + NumConfig++; > + Aperture |=3D 0x01; > + } > + > + // > + // if there is mem32 request, add to the mem32 aperture > + // > + if (ResourceRequestExisted (Mem32Node)) { > + NumConfig++; > + Aperture |=3D 0x02; > + } > + > + // > + // if there is pmem32 request, add to the pmem32 aperture > + // > + if (ResourceRequestExisted (PMem32Node)) { > + NumConfig++; > + Aperture |=3D 0x04; > + } > + > + // > + // if there is mem64 request, add to the mem64 aperture > + // > + if (ResourceRequestExisted (Mem64Node)) { > + NumConfig++; > + Aperture |=3D 0x08; > + } > + > + // > + // if there is pmem64 request, add to the pmem64 aperture > + // > + if (ResourceRequestExisted (PMem64Node)) { > + NumConfig++; > + Aperture |=3D 0x10; > + } > + > + if (NumConfig !=3D 0) { > + > + // > + // If there is at least one type of resource request, > + // allocate a acpi resource node > + // > + Configuration =3D AllocateZeroPool (sizeof > (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof > (EFI_ACPI_END_TAG_DESCRIPTOR)); > + if (Configuration =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Ptr =3D (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; > + > + // > + // Deal with io aperture > + // > + if ((Aperture & 0x01) !=3D 0) { > + Ptr->Desc =3D ACPI_ADDRESS_SPACE_DESCRIPTOR; > + Ptr->Len =3D (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIP= TOR) > - 3); > + // > + // Io > + // > + Ptr->ResType =3D ACPI_ADDRESS_SPACE_TYPE_IO; > + // > + // non ISA range > + // > + Ptr->SpecificFlag =3D 1; > + Ptr->AddrLen =3D IoNode->Length; > + Ptr->AddrRangeMax =3D IoNode->Alignment; > + > + Ptr++; > + } > + // > + // Deal with mem32 aperture > + // > + if ((Aperture & 0x02) !=3D 0) { > + Ptr->Desc =3D ACPI_ADDRESS_SPACE_DESCRIPTOR; > + Ptr->Len =3D (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIP= TOR) > - 3); > + // > + // Mem > + // > + Ptr->ResType =3D ACPI_ADDRESS_SPACE_TYPE_MEM; > + // > + // Nonprefechable > + // > + Ptr->SpecificFlag =3D 0; > + // > + // 32 bit > + // > + Ptr->AddrSpaceGranularity =3D 32; > + Ptr->AddrLen =3D Mem32Node->Length; > + Ptr->AddrRangeMax =3D Mem32Node->Alignment; > + > + Ptr++; > + } > + > + // > + // Deal with Pmem32 aperture > + // > + if ((Aperture & 0x04) !=3D 0) { > + Ptr->Desc =3D ACPI_ADDRESS_SPACE_DESCRIPTOR; > + Ptr->Len =3D (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIP= TOR) > - 3); > + // > + // Mem > + // > + Ptr->ResType =3D ACPI_ADDRESS_SPACE_TYPE_MEM; > + // > + // prefechable > + // > + Ptr->SpecificFlag =3D 0x6; > + // > + // 32 bit > + // > + Ptr->AddrSpaceGranularity =3D 32; > + Ptr->AddrLen =3D PMem32Node->Length; > + Ptr->AddrRangeMax =3D PMem32Node->Alignment; > + > + Ptr++; > + } > + // > + // Deal with mem64 aperture > + // > + if ((Aperture & 0x08) !=3D 0) { > + Ptr->Desc =3D ACPI_ADDRESS_SPACE_DESCRIPTOR; > + Ptr->Len =3D (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIP= TOR) > - 3); > + // > + // Mem > + // > + Ptr->ResType =3D ACPI_ADDRESS_SPACE_TYPE_MEM; > + // > + // nonprefechable > + // > + Ptr->SpecificFlag =3D 0; > + // > + // 64 bit > + // > + Ptr->AddrSpaceGranularity =3D 64; > + Ptr->AddrLen =3D Mem64Node->Length; > + Ptr->AddrRangeMax =3D Mem64Node->Alignment; > + > + Ptr++; > + } > + // > + // Deal with Pmem64 aperture > + // > + if ((Aperture & 0x10) !=3D 0) { > + Ptr->Desc =3D ACPI_ADDRESS_SPACE_DESCRIPTOR; > + Ptr->Len =3D (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIP= TOR) > - 3); > + // > + // Mem > + // > + Ptr->ResType =3D ACPI_ADDRESS_SPACE_TYPE_MEM; > + // > + // prefechable > + // > + Ptr->SpecificFlag =3D 0x06; > + // > + // 64 bit > + // > + Ptr->AddrSpaceGranularity =3D 64; > + Ptr->AddrLen =3D PMem64Node->Length; > + Ptr->AddrRangeMax =3D PMem64Node->Alignment; > + > + Ptr++; > + } > + > + // > + // put the checksum > + // > + PtrEnd =3D (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr; > + > + PtrEnd->Desc =3D ACPI_END_TAG_DESCRIPTOR; > + PtrEnd->Checksum =3D 0; > + > + } else { > + > + // > + // If there is no resource request > + // > + Configuration =3D AllocateZeroPool (sizeof > (EFI_ACPI_END_TAG_DESCRIPTOR)); > + if (Configuration =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + PtrEnd =3D (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration= ); > + PtrEnd->Desc =3D ACPI_END_TAG_DESCRIPTOR; > + PtrEnd->Checksum =3D 0; > + } > + > + *Config =3D Configuration; > + > + return EFI_SUCCESS; > +} > + > +/** > + Get resource base from an acpi configuration descriptor. > + > + @param Config An acpi configuration descriptor. > + @param IoBase Output of I/O resource base address. > + @param Mem32Base Output of 32-bit memory base address. > + @param PMem32Base Output of 32-bit prefetchable memory base > address. > + @param Mem64Base Output of 64-bit memory base address. > + @param PMem64Base Output of 64-bit prefetchable memory base > address. > + > +**/ > +VOID > +GetResourceBase ( > + IN VOID *Config, > + OUT UINT64 *IoBase, > + OUT UINT64 *Mem32Base, > + OUT UINT64 *PMem32Base, > + OUT UINT64 *Mem64Base, > + OUT UINT64 *PMem64Base > + ) > +{ > + UINT8 *Temp; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; > + UINT64 ResStatus; > + > + ASSERT (Config !=3D NULL); > + > + *IoBase =3D 0xFFFFFFFFFFFFFFFFULL; > + *Mem32Base =3D 0xFFFFFFFFFFFFFFFFULL; > + *PMem32Base =3D 0xFFFFFFFFFFFFFFFFULL; > + *Mem64Base =3D 0xFFFFFFFFFFFFFFFFULL; > + *PMem64Base =3D 0xFFFFFFFFFFFFFFFFULL; > + > + Temp =3D (UINT8 *) Config; > + > + while (*Temp =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR) { > + > + Ptr =3D (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; > + ResStatus =3D Ptr->AddrTranslationOffset; > + > + if (ResStatus =3D=3D EFI_RESOURCE_SATISFIED) { > + > + switch (Ptr->ResType) { > + > + // > + // Memory type aperture > + // > + case 0: > + > + // > + // Check to see the granularity > + // > + if (Ptr->AddrSpaceGranularity =3D=3D 32) { > + if ((Ptr->SpecificFlag & 0x06) !=3D 0) { > + *PMem32Base =3D Ptr->AddrRangeMin; > + } else { > + *Mem32Base =3D Ptr->AddrRangeMin; > + } > + } > + > + if (Ptr->AddrSpaceGranularity =3D=3D 64) { > + if ((Ptr->SpecificFlag & 0x06) !=3D 0) { > + *PMem64Base =3D Ptr->AddrRangeMin; > + } else { > + *Mem64Base =3D Ptr->AddrRangeMin; > + } > + } > + break; > + > + case 1: > + > + // > + // Io type aperture > + // > + *IoBase =3D Ptr->AddrRangeMin; > + break; > + > + default: > + break; > + > + } > + // > + // End switch > + // > + } > + // > + // End for > + // > + Temp +=3D sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); > + } > +} > + > +/** > + Enumerate pci bridge, allocate resource and determine attribute > + for devices on this bridge. > + > + @param BridgeDev Pointer to instance of bridge device. > + > + @retval EFI_SUCCESS Successfully enumerated PCI bridge. > + @retval other Failed to enumerate. > + > +**/ > +EFI_STATUS > +PciBridgeEnumerator ( > + IN PCI_IO_DEVICE *BridgeDev > + ) > +{ > + UINT8 SubBusNumber; > + UINT8 StartBusNumber; > + EFI_PCI_IO_PROTOCOL *PciIo; > + EFI_STATUS Status; > + > + SubBusNumber =3D 0; > + StartBusNumber =3D 0; > + PciIo =3D &(BridgeDev->PciIo); > + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, = 1, > &StartBusNumber); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D PciAssignBusNumber ( > + BridgeDev, > + StartBusNumber, > + &SubBusNumber > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D PciPciDeviceInfoCollector (BridgeDev, StartBusNumber); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D PciBridgeResourceAllocator (BridgeDev); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D DetermineDeviceAttribute (BridgeDev); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + return EFI_SUCCESS; > + > +} > + > +/** > + Allocate all kinds of resource for PCI bridge. > + > + @param Bridge Pointer to bridge instance. > + > + @retval EFI_SUCCESS Successfully allocated resource for PCI bridge. > + @retval other Failed to allocate resource for bridge. > + > +**/ > +EFI_STATUS > +PciBridgeResourceAllocator ( > + IN PCI_IO_DEVICE *Bridge > + ) > +{ > + PCI_RESOURCE_NODE *IoBridge; > + PCI_RESOURCE_NODE *Mem32Bridge; > + PCI_RESOURCE_NODE *PMem32Bridge; > + PCI_RESOURCE_NODE *Mem64Bridge; > + PCI_RESOURCE_NODE *PMem64Bridge; > + UINT64 IoBase; > + UINT64 Mem32Base; > + UINT64 PMem32Base; > + UINT64 Mem64Base; > + UINT64 PMem64Base; > + EFI_STATUS Status; > + > + IoBridge =3D CreateResourceNode ( > + Bridge, > + 0, > + Bridge->BridgeIoAlignment, > + 0, > + PciBarTypeIo16, > + PciResUsageTypical > + ); > + > + Mem32Bridge =3D CreateResourceNode ( > + Bridge, > + 0, > + 0xFFFFF, > + 0, > + PciBarTypeMem32, > + PciResUsageTypical > + ); > + > + PMem32Bridge =3D CreateResourceNode ( > + Bridge, > + 0, > + 0xFFFFF, > + 0, > + PciBarTypePMem32, > + PciResUsageTypical > + ); > + > + Mem64Bridge =3D CreateResourceNode ( > + Bridge, > + 0, > + 0xFFFFF, > + 0, > + PciBarTypeMem64, > + PciResUsageTypical > + ); > + > + PMem64Bridge =3D CreateResourceNode ( > + Bridge, > + 0, > + 0xFFFFF, > + 0, > + PciBarTypePMem64, > + PciResUsageTypical > + ); > + > + // > + // Create resourcemap by going through all the devices subject to this= root > bridge > + // > + CreateResourceMap ( > + Bridge, > + IoBridge, > + Mem32Bridge, > + PMem32Bridge, > + Mem64Bridge, > + PMem64Bridge > + ); > + > + Status =3D GetResourceBaseFromBridge ( > + Bridge, > + &IoBase, > + &Mem32Base, > + &PMem32Base, > + &Mem64Base, > + &PMem64Base > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Program IO resources > + // > + ProgramResource ( > + IoBase, > + IoBridge > + ); > + > + // > + // Program Mem32 resources > + // > + ProgramResource ( > + Mem32Base, > + Mem32Bridge > + ); > + > + // > + // Program PMem32 resources > + // > + ProgramResource ( > + PMem32Base, > + PMem32Bridge > + ); > + > + // > + // Program Mem64 resources > + // > + ProgramResource ( > + Mem64Base, > + Mem64Bridge > + ); > + > + // > + // Program PMem64 resources > + // > + ProgramResource ( > + PMem64Base, > + PMem64Bridge > + ); > + > + DestroyResourceTree (IoBridge); > + DestroyResourceTree (Mem32Bridge); > + DestroyResourceTree (PMem32Bridge); > + DestroyResourceTree (PMem64Bridge); > + DestroyResourceTree (Mem64Bridge); > + > + gBS->FreePool (IoBridge); > + gBS->FreePool (Mem32Bridge); > + gBS->FreePool (PMem32Bridge); > + gBS->FreePool (PMem64Bridge); > + gBS->FreePool (Mem64Bridge); > + > + return EFI_SUCCESS; > +} > + > +/** > + Get resource base address for a pci bridge device. > + > + @param Bridge Given Pci driver instance. > + @param IoBase Output for base address of I/O type resource. > + @param Mem32Base Output for base address of 32-bit memory type > resource. > + @param PMem32Base Ooutput for base address of 32-bit Pmemory type > resource. > + @param Mem64Base Output for base address of 64-bit memory type > resource. > + @param PMem64Base Output for base address of 64-bit Pmemory type > resource. > + > + @retval EFI_SUCCESS Successfully got resource base address. > + @retval EFI_OUT_OF_RESOURCES PCI bridge is not available. > + > +**/ > +EFI_STATUS > +GetResourceBaseFromBridge ( > + IN PCI_IO_DEVICE *Bridge, > + OUT UINT64 *IoBase, > + OUT UINT64 *Mem32Base, > + OUT UINT64 *PMem32Base, > + OUT UINT64 *Mem64Base, > + OUT UINT64 *PMem64Base > + ) > +{ > + if (!Bridge->Allocated) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + *IoBase =3D gAllOne; > + *Mem32Base =3D gAllOne; > + *PMem32Base =3D gAllOne; > + *Mem64Base =3D gAllOne; > + *PMem64Base =3D gAllOne; > + > + if (IS_PCI_BRIDGE (&Bridge->Pci)) { > + > + if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) { > + *IoBase =3D Bridge->PciBar[PPB_IO_RANGE].BaseAddress; > + } > + > + if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) { > + *Mem32Base =3D Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress; > + } > + > + if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) { > + *PMem32Base =3D Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress; > + } > + > + if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) { > + *PMem64Base =3D Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress; > + } else { > + *PMem64Base =3D gAllOne; > + } > + > + } > + > + if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) { > + if (Bridge->PciBar[P2C_IO_1].Length > 0) { > + *IoBase =3D Bridge->PciBar[P2C_IO_1].BaseAddress; > + } else { > + if (Bridge->PciBar[P2C_IO_2].Length > 0) { > + *IoBase =3D Bridge->PciBar[P2C_IO_2].BaseAddress; > + } > + } > + > + if (Bridge->PciBar[P2C_MEM_1].Length > 0) { > + if (Bridge->PciBar[P2C_MEM_1].BarType =3D=3D PciBarTypePMem32) { > + *PMem32Base =3D Bridge->PciBar[P2C_MEM_1].BaseAddress; > + } > + > + if (Bridge->PciBar[P2C_MEM_1].BarType =3D=3D PciBarTypeMem32) { > + *Mem32Base =3D Bridge->PciBar[P2C_MEM_1].BaseAddress; > + } > + } > + > + if (Bridge->PciBar[P2C_MEM_2].Length > 0) { > + if (Bridge->PciBar[P2C_MEM_2].BarType =3D=3D PciBarTypePMem32) { > + *PMem32Base =3D Bridge->PciBar[P2C_MEM_2].BaseAddress; > + } > + > + if (Bridge->PciBar[P2C_MEM_2].BarType =3D=3D PciBarTypeMem32) { > + *Mem32Base =3D Bridge->PciBar[P2C_MEM_2].BaseAddress; > + } > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + These are the notifications from the PCI bus driver that it is about = to enter > a certain > + phase of the PCI enumeration process. > + > + This member function can be used to notify the host bridge driver to > perform specific actions, > + including any chipset-specific initialization, so that the chipset is= ready to > enter the next phase. > + Eight notification points are defined at this time. See belows: > + EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI > apertures and internal data > + structures. The PCI enumerator= should issue this > notification > + before starting a fresh enumer= ation process. > Enumeration cannot > + be restarted after sending any= other notification such > as > + EfiPciHostBridgeBeginBusAlloca= tion. > + EfiPciHostBridgeBeginBusAllocation The bus allocation phase is ab= out to > begin. No specific action is > + required here. This notificati= on can be used to perform > any > + chipset-specific programming. > + EfiPciHostBridgeEndBusAllocation The bus allocation and bus > programming phase is complete. No > + specific action is required he= re. This notification can be > used to > + perform any chipset-specific p= rogramming. > + EfiPciHostBridgeBeginResourceAllocation > + The resource allocation phase = is about to begin. No > specific > + action is required here. This = notification can be used to > perform > + any chipset-specific programmi= ng. > + EfiPciHostBridgeAllocateResources Allocates resources per previo= usly > submitted requests for all the PCI > + root bridges. These resource s= ettings are returned on > the next call to > + GetProposedResources(). Before= calling NotifyPhase() > with a Phase of > + EfiPciHostBridgeAllocateResour= ce, the PCI bus > enumerator is responsible > + for gathering I/O and memory r= equests for > + all the PCI root bridges and s= ubmitting these requests > using > + SubmitResources(). This functi= on pads the resource > amount > + to suit the root bridge hardwa= re, takes care of > dependencies between > + the PCI root bridges, and call= s the Global Coherency > Domain (GCD) > + with the allocation request. I= n the case of padding, the > allocated range > + could be bigger than what was = requested. > + EfiPciHostBridgeSetResources Programs the host bridge hardw= are to > decode previously allocated > + resources (proposed resources)= for all the PCI root > bridges. After the > + hardware is programmed, reassi= gning resources will > not be supported. > + The bus settings are not affec= ted. > + EfiPciHostBridgeFreeResources Deallocates resources that wer= e > previously allocated for all the PCI > + root bridges and resets the I/= O and memory apertures > to their initial > + state. The bus settings are no= t affected. If the request > to allocate > + resources fails, the PCI enume= rator can use this > notification to > + deallocate previous resources,= adjust the requests, > and retry > + allocation. > + EfiPciHostBridgeEndResourceAllocation The resource allocation phase = is > completed. No specific action is > + required here. This notificati= on can be used to perform > any chipsetspecific > + programming. > + > + @param[in] PciResAlloc The instance pointer of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > + @param[in] Phase The phase during enumeration > + > + @retval EFI_NOT_READY This phase cannot be entered at this t= ime. > For example, this error > + is valid for a Phase of EfiPciHostBrid= geAllocateResources if > + SubmitResources() has not been called = for one or more > + PCI root bridges before this call > + @retval EFI_DEVICE_ERROR Programming failed due to a hardware > error. This error is valid > + for a Phase of EfiPciHostBridgeSetReso= urces. > + @retval EFI_INVALID_PARAMETER Invalid phase parameter > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + This error is valid for a Phase of > EfiPciHostBridgeAllocateResources if the > + previously submitted resource requests= cannot be fulfilled > or > + were only partially fulfilled. > + @retval EFI_SUCCESS The notification was accepted without = any > errors. > + > +**/ > +EFI_STATUS > +NotifyPhase ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc, > + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase > + ) > +{ > + EFI_HANDLE HostBridgeHandle; > + EFI_HANDLE RootBridgeHandle; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + EFI_STATUS Status; > + > + HostBridgeHandle =3D NULL; > + RootBridgeHandle =3D NULL; > + if (gPciPlatformProtocol !=3D NULL) { > + // > + // Get Host Bridge Handle. > + // > + PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle); > + > + // > + // Get the rootbridge Io protocol to find the host bridge handle > + // > + Status =3D gBS->HandleProtocol ( > + RootBridgeHandle, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + HostBridgeHandle =3D PciRootBridgeIo->ParentHandle; > + > + // > + // Call PlatformPci::PlatformNotify() if the protocol is present. > + // > + gPciPlatformProtocol->PlatformNotify ( > + gPciPlatformProtocol, > + HostBridgeHandle, > + Phase, > + ChipsetEntry > + ); > + } else if (gPciOverrideProtocol !=3D NULL){ > + // > + // Get Host Bridge Handle. > + // > + PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle); > + > + // > + // Get the rootbridge Io protocol to find the host bridge handle > + // > + Status =3D gBS->HandleProtocol ( > + RootBridgeHandle, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + HostBridgeHandle =3D PciRootBridgeIo->ParentHandle; > + > + // > + // Call PlatformPci::PhaseNotify() if the protocol is present. > + // > + gPciOverrideProtocol->PlatformNotify ( > + gPciOverrideProtocol, > + HostBridgeHandle, > + Phase, > + ChipsetEntry > + ); > + } > + > + Status =3D PciResAlloc->NotifyPhase ( > + PciResAlloc, > + Phase > + ); > + > + if (gPciPlatformProtocol !=3D NULL) { > + // > + // Call PlatformPci::PlatformNotify() if the protocol is present. > + // > + gPciPlatformProtocol->PlatformNotify ( > + gPciPlatformProtocol, > + HostBridgeHandle, > + Phase, > + ChipsetExit > + ); > + > + } else if (gPciOverrideProtocol !=3D NULL) { > + // > + // Call PlatformPci::PhaseNotify() if the protocol is present. > + // > + gPciOverrideProtocol->PlatformNotify ( > + gPciOverrideProtocol, > + HostBridgeHandle, > + Phase, > + ChipsetExit > + ); > + } > + > + return Status; > +} > + > +/** > + Provides the hooks from the PCI bus driver to every PCI controller > (device/function) at various > + stages of the PCI enumeration process that allow the host bridge drive= r to > preinitialize individual > + PCI controllers before enumeration. > + > + This function is called during the PCI enumeration process. No specifi= c > action is expected from this > + member function. It allows the host bridge driver to preinitialize ind= ividual > PCI controllers before > + enumeration. > + > + @param Bridge Pointer to the > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. > + @param Bus The bus number of the pci device. > + @param Device The device number of the pci device. > + @param Func The function number of the pci device. > + @param Phase The phase of the PCI device enumeration. > + > + @retval EFI_SUCCESS The requested parameters were returne= d. > + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root > bridge handle. > + @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is > defined in > + EFI_PCI_CONTROLLER_RESOURCE_ALLOCATIO= N_PHASE. > + @retval EFI_DEVICE_ERROR Programming failed due to a hardware > error. The PCI enumerator should > + not enumerate this device, including = its child devices if it is > a PCI-to-PCI > + bridge. > + > +**/ > +EFI_STATUS > +PreprocessController ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func, > + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase > + ) > +{ > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS > RootBridgePciAddress; > + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc; > + EFI_HANDLE RootBridgeHandle; > + EFI_HANDLE HostBridgeHandle; > + EFI_STATUS Status; > + > + // > + // Get the host bridge handle > + // > + HostBridgeHandle =3D Bridge->PciRootBridgeIo->ParentHandle; > + > + // > + // Get the pci host bridge resource allocation protocol > + // > + Status =3D gBS->OpenProtocol ( > + HostBridgeHandle, > + &gEfiPciHostBridgeResourceAllocationProtocolGuid, > + (VOID **) &PciResAlloc, > + NULL, > + NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Get Root Brige Handle > + // > + while (Bridge->Parent !=3D NULL) { > + Bridge =3D Bridge->Parent; > + } > + > + RootBridgeHandle =3D Bridge->Handle; > + > + RootBridgePciAddress.Register =3D 0; > + RootBridgePciAddress.Function =3D Func; > + RootBridgePciAddress.Device =3D Device; > + RootBridgePciAddress.Bus =3D Bus; > + RootBridgePciAddress.ExtendedRegister =3D 0; > + > + if (gPciPlatformProtocol !=3D NULL) { > + // > + // Call PlatformPci::PrepController() if the protocol is present. > + // > + gPciPlatformProtocol->PlatformPrepController ( > + gPciPlatformProtocol, > + HostBridgeHandle, > + RootBridgeHandle, > + RootBridgePciAddress, > + Phase, > + ChipsetEntry > + ); > + } else if (gPciOverrideProtocol !=3D NULL) { > + // > + // Call PlatformPci::PrepController() if the protocol is present. > + // > + gPciOverrideProtocol->PlatformPrepController ( > + gPciOverrideProtocol, > + HostBridgeHandle, > + RootBridgeHandle, > + RootBridgePciAddress, > + Phase, > + ChipsetEntry > + ); > + } > + > + Status =3D PciResAlloc->PreprocessController ( > + PciResAlloc, > + RootBridgeHandle, > + RootBridgePciAddress, > + Phase > + ); > + > + if (gPciPlatformProtocol !=3D NULL) { > + // > + // Call PlatformPci::PrepController() if the protocol is present. > + // > + gPciPlatformProtocol->PlatformPrepController ( > + gPciPlatformProtocol, > + HostBridgeHandle, > + RootBridgeHandle, > + RootBridgePciAddress, > + Phase, > + ChipsetExit > + ); > + } else if (gPciOverrideProtocol !=3D NULL) { > + // > + // Call PlatformPci::PrepController() if the protocol is present. > + // > + gPciOverrideProtocol->PlatformPrepController ( > + gPciOverrideProtocol, > + HostBridgeHandle, > + RootBridgeHandle, > + RootBridgePciAddress, > + Phase, > + ChipsetExit > + ); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This function allows the PCI bus driver to be notified to act as reque= sted > when a hot-plug event has > + happened on the hot-plug controller. Currently, the operations include > add operation and remove operation.. > + > + @param This A pointer to the hot plug request protocol= . > + @param Operation The operation the PCI bus driver is reques= ted to > make. > + @param Controller The handle of the hot-plug controller. > + @param RemainingDevicePath The remaining device path for the PCI-like > hot-plug device. > + @param NumberOfChildren The number of child handles. > + For a add operation, it is an output param= eter. > + For a remove operation, it's an input para= meter. > + @param ChildHandleBuffer The buffer which contains the child handle= s. > + > + @retval EFI_INVALID_PARAMETER Operation is not a legal value. > + Controller is NULL or not a valid handl= e. > + NumberOfChildren is NULL. > + ChildHandleBuffer is NULL while Operati= on is add. > + @retval EFI_OUT_OF_RESOURCES There are no enough resources to start > the devices. > + @retval EFI_NOT_FOUND Can not find bridge according to contro= ller > handle. > + @retval EFI_SUCCESS The handles for the specified device ha= ve been > created or destroyed > + as requested, and for an add operation,= the new handles > are > + returned in ChildHandleBuffer. > +**/ > +EFI_STATUS > +EFIAPI > +PciHotPlugRequestNotify ( > + IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This, > + IN EFI_PCI_HOTPLUG_OPERATION Operation, > + IN EFI_HANDLE Controller, > + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL, > + IN OUT UINT8 *NumberOfChildren, > + IN OUT EFI_HANDLE * ChildHandleBuffer > + ) > +{ > + PCI_IO_DEVICE *Bridge; > + PCI_IO_DEVICE *Temp; > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINTN Index; > + EFI_HANDLE RootBridgeHandle; > + EFI_STATUS Status; > + > + // > + // Check input parameter validity > + // > + if ((Controller =3D=3D NULL) || (NumberOfChildren =3D=3D NULL)){ > + return EFI_INVALID_PARAMETER; > + } > + > + if ((Operation !=3D EfiPciHotPlugRequestAdd) && (Operation !=3D > EfiPciHotplugRequestRemove)) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Operation =3D=3D EfiPciHotPlugRequestAdd){ > + if (ChildHandleBuffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + } else if ((Operation =3D=3D EfiPciHotplugRequestRemove) && > (*NumberOfChildren !=3D 0)) { > + if (ChildHandleBuffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + } > + > + Status =3D gBS->OpenProtocol ( > + Controller, > + &gEfiPciIoProtocolGuid, > + (VOID **) &PciIo, > + gPciBusDriverBinding.DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + Bridge =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); > + > + // > + // Get root bridge handle > + // > + Temp =3D Bridge; > + while (Temp->Parent !=3D NULL) { > + Temp =3D Temp->Parent; > + } > + > + RootBridgeHandle =3D Temp->Handle; > + > + if (Operation =3D=3D EfiPciHotPlugRequestAdd) { > + // > + // Report Status Code to indicate hot plug happens > + // > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_PROGRESS_CODE, > + (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG), > + Temp->DevicePath > + ); > + > + if (NumberOfChildren !=3D NULL) { > + *NumberOfChildren =3D 0; > + } > + > + if (IsListEmpty (&Bridge->ChildList)) { > + > + Status =3D PciBridgeEnumerator (Bridge); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + Status =3D StartPciDevicesOnBridge ( > + RootBridgeHandle, > + Bridge, > + RemainingDevicePath, > + NumberOfChildren, > + ChildHandleBuffer > + ); > + > + return Status; > + } > + > + if (Operation =3D=3D EfiPciHotplugRequestRemove) { > + > + if (*NumberOfChildren =3D=3D 0) { > + // > + // Remove all devices on the bridge > + // > + RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge); > + return EFI_SUCCESS; > + > + } > + > + for (Index =3D 0; Index < *NumberOfChildren; Index++) { > + // > + // De register all the pci device > + // > + Status =3D DeRegisterPciDevice (RootBridgeHandle, > ChildHandleBuffer[Index]); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + } > + // > + // End for > + // > + return EFI_SUCCESS; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Search hostbridge according to given handle > + > + @param RootBridgeHandle Host bridge handle. > + > + @retval TRUE Found host bridge handle. > + @retval FALSE Not found hot bridge handle. > + > +**/ > +BOOLEAN > +SearchHostBridgeHandle ( > + IN EFI_HANDLE RootBridgeHandle > + ) > +{ > + EFI_HANDLE HostBridgeHandle; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + UINTN Index; > + EFI_STATUS Status; > + > + // > + // Get the rootbridge Io protocol to find the host bridge handle > + // > + Status =3D gBS->OpenProtocol ( > + RootBridgeHandle, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo, > + gPciBusDriverBinding.DriverBindingHandle, > + RootBridgeHandle, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + HostBridgeHandle =3D PciRootBridgeIo->ParentHandle; > + for (Index =3D 0; Index < gPciHostBridgeNumber; Index++) { > + if (HostBridgeHandle =3D=3D gPciHostBrigeHandles[Index]) { > + return TRUE; > + } > + } > + > + return FALSE; > +} > + > +/** > + Add host bridge handle to global variable for enumerating. > + > + @param HostBridgeHandle Host bridge handle. > + > + @retval EFI_SUCCESS Successfully added host bridge. > + @retval EFI_ABORTED Host bridge is NULL, or given host bridge > + has been in host bridge list. > + > +**/ > +EFI_STATUS > +AddHostBridgeEnumerator ( > + IN EFI_HANDLE HostBridgeHandle > + ) > +{ > + UINTN Index; > + > + if (HostBridgeHandle =3D=3D NULL) { > + return EFI_ABORTED; > + } > + > + for (Index =3D 0; Index < gPciHostBridgeNumber; Index++) { > + if (HostBridgeHandle =3D=3D gPciHostBrigeHandles[Index]) { > + return EFI_ABORTED; > + } > + } > + > + if (Index < PCI_MAX_HOST_BRIDGE_NUM) { > + gPciHostBrigeHandles[Index] =3D HostBridgeHandle; > + gPciHostBridgeNumber++; > + } > + > + return EFI_SUCCESS; > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumerator.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumerator.h > new file mode 100644 > index 0000000000..2a34c9043c > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumerator.h > @@ -0,0 +1,515 @@ > +/** @file > + PCI bus enumeration logic function declaration for PCI bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_ENUMERATOR_H_ > +#define _EFI_PCI_ENUMERATOR_H_ > + > +#include "PciResourceSupport.h" > + > +/** > + This routine is used to enumerate entire pci bus system > + in a given platform. > + > + @param Controller Parent controller handle. > + @param HostBridgeHandle Host bridge handle. > + > + @retval EFI_SUCCESS PCI enumeration finished successfully. > + @retval other Some error occurred when enumerating the pci bu= s > system. > + > +**/ > +EFI_STATUS > +PciEnumerator ( > + IN EFI_HANDLE Controller, > + IN EFI_HANDLE HostBridgeHandle > + ); > + > +/** > + Enumerate PCI root bridge. > + > + @param PciResAlloc Pointer to protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + @param RootBridgeDev Instance of root bridge device. > + > + @retval EFI_SUCCESS Successfully enumerated root bridge. > + @retval other Failed to enumerate root bridge. > + > +**/ > +EFI_STATUS > +PciRootBridgeEnumerator ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc, > + IN PCI_IO_DEVICE *RootBridgeDev > + ); > + > +/** > + This routine is used to process all PCI devices' Option Rom > + on a certain root bridge. > + > + @param Bridge Given parent's root bridge. > + @param RomBase Base address of ROM driver loaded from. > + @param MaxLength Maximum rom size. > + > +**/ > +VOID > +ProcessOptionRom ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT64 RomBase, > + IN UINT64 MaxLength > + ); > + > +/** > + This routine is used to assign bus number to the given PCI bus system > + > + @param Bridge Parent root bridge instance. > + @param StartBusNumber Number of beginning. > + @param SubBusNumber The number of sub bus. > + > + @retval EFI_SUCCESS Successfully assigned bus number. > + @retval EFI_DEVICE_ERROR Failed to assign bus number. > + > +**/ > +EFI_STATUS > +PciAssignBusNumber ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber, > + OUT UINT8 *SubBusNumber > + ); > + > +/** > + This routine is used to determine the root bridge attribute by interfa= cing > + the host bridge resource allocation protocol. > + > + @param PciResAlloc Protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > + @param RootBridgeDev Root bridge instance > + > + @retval EFI_SUCCESS Successfully got root bridge's attribute. > + @retval other Failed to get attribute. > + > +**/ > +EFI_STATUS > +DetermineRootBridgeAttributes ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc, > + IN PCI_IO_DEVICE *RootBridgeDev > + ); > + > +/** > + Get Max Option Rom size on specified bridge. > + > + @param Bridge Given bridge device instance. > + > + @return Max size of option rom needed. > + > +**/ > +UINT32 > +GetMaxOptionRomSize ( > + IN PCI_IO_DEVICE *Bridge > + ); > + > +/** > + Process attributes of devices on this host bridge > + > + @param PciResAlloc Protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + > + @retval EFI_SUCCESS Successfully process attribute. > + @retval EFI_NOT_FOUND Can not find the specific root bridge device. > + @retval other Failed to determine the root bridge device's att= ribute. > + > +**/ > +EFI_STATUS > +PciHostBridgeDeviceAttribute ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ); > + > +/** > + Get resource allocation status from the ACPI resource descriptor. > + > + @param AcpiConfig Point to Acpi configuration table. > + @param IoResStatus Return the status of I/O resource. > + @param Mem32ResStatus Return the status of 32-bit Memory resource. > + @param PMem32ResStatus Return the status of 32-bit Prefetchable > Memory resource. > + @param Mem64ResStatus Return the status of 64-bit Memory resource. > + @param PMem64ResStatus Return the status of 64-bit Prefetchable > Memory resource. > + > +**/ > +VOID > +GetResourceAllocationStatus ( > + VOID *AcpiConfig, > + OUT UINT64 *IoResStatus, > + OUT UINT64 *Mem32ResStatus, > + OUT UINT64 *PMem32ResStatus, > + OUT UINT64 *Mem64ResStatus, > + OUT UINT64 *PMem64ResStatus > + ); > + > +/** > + Remove a PCI device from device pool and mark its bar. > + > + @param PciDevice Instance of Pci device. > + > + @retval EFI_SUCCESS Successfully remove the PCI device. > + @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge. > + > +**/ > +EFI_STATUS > +RejectPciDevice ( > + IN PCI_IO_DEVICE *PciDevice > + ); > + > +/** > + Determine whethter a PCI device can be rejected. > + > + @param PciResNode Pointer to Pci resource node instance. > + > + @retval TRUE The PCI device can be rejected. > + @retval TRUE The PCI device cannot be rejected. > + > +**/ > +BOOLEAN > +IsRejectiveDevice ( > + IN PCI_RESOURCE_NODE *PciResNode > + ); > + > +/** > + Compare two resource nodes and get the larger resource consumer. > + > + @param PciResNode1 resource node 1 want to be compared > + @param PciResNode2 resource node 2 want to be compared > + > + @return Larger resource node. > + > +**/ > +PCI_RESOURCE_NODE * > +GetLargerConsumerDevice ( > + IN PCI_RESOURCE_NODE *PciResNode1, > + IN PCI_RESOURCE_NODE *PciResNode2 > + ); > + > +/** > + Get the max resource consumer in the host resource pool. > + > + @param ResPool Pointer to resource pool node. > + > + @return The max resource consumer in the host resource pool. > + > +**/ > +PCI_RESOURCE_NODE * > +GetMaxResourceConsumerDevice ( > + IN PCI_RESOURCE_NODE *ResPool > + ); > + > +/** > + Adjust host bridge allocation so as to reduce resource requirement > + > + @param IoPool Pointer to instance of I/O resource Node. > + @param Mem32Pool Pointer to instance of 32-bit memory resource > Node. > + @param PMem32Pool Pointer to instance of 32-bit Prefetchable > memory resource node. > + @param Mem64Pool Pointer to instance of 64-bit memory resource > node. > + @param PMem64Pool Pointer to instance of 64-bit Prefetchable > memory resource node. > + @param IoResStatus Status of I/O resource Node. > + @param Mem32ResStatus Status of 32-bit memory resource Node. > + @param PMem32ResStatus Status of 32-bit Prefetchable memory > resource node. > + @param Mem64ResStatus Status of 64-bit memory resource node. > + @param PMem64ResStatus Status of 64-bit Prefetchable memory > resource node. > + > + @retval EFI_SUCCESS Successfully adjusted resource on host bridge. > + @retval EFI_ABORTED Host bridge hasn't this resource type or no > resource be adjusted. > + > +**/ > +EFI_STATUS > +PciHostBridgeAdjustAllocation ( > + IN PCI_RESOURCE_NODE *IoPool, > + IN PCI_RESOURCE_NODE *Mem32Pool, > + IN PCI_RESOURCE_NODE *PMem32Pool, > + IN PCI_RESOURCE_NODE *Mem64Pool, > + IN PCI_RESOURCE_NODE *PMem64Pool, > + IN UINT64 IoResStatus, > + IN UINT64 Mem32ResStatus, > + IN UINT64 PMem32ResStatus, > + IN UINT64 Mem64ResStatus, > + IN UINT64 PMem64ResStatus > + ); > + > +/** > + Summary requests for all resource type, and construct ACPI resource > + requestor instance. > + > + @param Bridge detecting bridge > + @param IoNode Pointer to instance of I/O resource Node > + @param Mem32Node Pointer to instance of 32-bit memory resource > Node > + @param PMem32Node Pointer to instance of 32-bit Pmemory resource > node > + @param Mem64Node Pointer to instance of 64-bit memory resource > node > + @param PMem64Node Pointer to instance of 64-bit Pmemory resource > node > + @param Config Output buffer holding new constructed APCI res= ource > requestor > + > + @retval EFI_SUCCESS Successfully constructed ACPI resource. > + @retval EFI_OUT_OF_RESOURCES No memory available. > + > +**/ > +EFI_STATUS > +ConstructAcpiResourceRequestor ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node, > + OUT VOID **Config > + ); > + > +/** > + Get resource base from an acpi configuration descriptor. > + > + @param Config An acpi configuration descriptor. > + @param IoBase Output of I/O resource base address. > + @param Mem32Base Output of 32-bit memory base address. > + @param PMem32Base Output of 32-bit prefetchable memory base > address. > + @param Mem64Base Output of 64-bit memory base address. > + @param PMem64Base Output of 64-bit prefetchable memory base > address. > + > +**/ > +VOID > +GetResourceBase ( > + IN VOID *Config, > + OUT UINT64 *IoBase, > + OUT UINT64 *Mem32Base, > + OUT UINT64 *PMem32Base, > + OUT UINT64 *Mem64Base, > + OUT UINT64 *PMem64Base > + ); > + > +/** > + Enumerate pci bridge, allocate resource and determine attribute > + for devices on this bridge. > + > + @param BridgeDev Pointer to instance of bridge device. > + > + @retval EFI_SUCCESS Successfully enumerated PCI bridge. > + @retval other Failed to enumerate. > + > +**/ > +EFI_STATUS > +PciBridgeEnumerator ( > + IN PCI_IO_DEVICE *BridgeDev > + ); > + > +/** > + Allocate all kinds of resource for PCI bridge. > + > + @param Bridge Pointer to bridge instance. > + > + @retval EFI_SUCCESS Successfully allocated resource for PCI bridge. > + @retval other Failed to allocate resource for bridge. > + > +**/ > +EFI_STATUS > +PciBridgeResourceAllocator ( > + IN PCI_IO_DEVICE *Bridge > + ); > + > +/** > + Get resource base address for a pci bridge device. > + > + @param Bridge Given Pci driver instance. > + @param IoBase Output for base address of I/O type resource. > + @param Mem32Base Output for base address of 32-bit memory type > resource. > + @param PMem32Base Ooutput for base address of 32-bit Pmemory type > resource. > + @param Mem64Base Output for base address of 64-bit memory type > resource. > + @param PMem64Base Output for base address of 64-bit Pmemory type > resource. > + > + @retval EFI_SUCCESS Successfully got resource base address. > + @retval EFI_OUT_OF_RESOURCES PCI bridge is not available. > + > +**/ > +EFI_STATUS > +GetResourceBaseFromBridge ( > + IN PCI_IO_DEVICE *Bridge, > + OUT UINT64 *IoBase, > + OUT UINT64 *Mem32Base, > + OUT UINT64 *PMem32Base, > + OUT UINT64 *Mem64Base, > + OUT UINT64 *PMem64Base > + ); > + > +/** > + Process Option Rom on this host bridge > + > + @param PciResAlloc Pointer to instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + > + @retval EFI_NOT_FOUND Can not find the root bridge instance. > + @retval EFI_SUCCESS Success process. > +**/ > +EFI_STATUS > +PciHostBridgeP2CProcess ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ); > + > +/** > + These are the notifications from the PCI bus driver that it is about = to enter > a certain > + phase of the PCI enumeration process. > + > + This member function can be used to notify the host bridge driver to > perform specific actions, > + including any chipset-specific initialization, so that the chipset is= ready to > enter the next phase. > + Eight notification points are defined at this time. See belows: > + EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI > apertures and internal data > + structures. The PCI enumerator= should issue this > notification > + before starting a fresh enumer= ation process. > Enumeration cannot > + be restarted after sending any= other notification such > as > + EfiPciHostBridgeBeginBusAlloca= tion. > + EfiPciHostBridgeBeginBusAllocation The bus allocation phase is ab= out to > begin. No specific action is > + required here. This notificati= on can be used to perform > any > + chipset-specific programming. > + EfiPciHostBridgeEndBusAllocation The bus allocation and bus > programming phase is complete. No > + specific action is required he= re. This notification can be > used to > + perform any chipset-specific p= rogramming. > + EfiPciHostBridgeBeginResourceAllocation > + The resource allocation phase = is about to begin. No > specific > + action is required here. This = notification can be used to > perform > + any chipset-specific programmi= ng. > + EfiPciHostBridgeAllocateResources Allocates resources per previo= usly > submitted requests for all the PCI > + root bridges. These resource s= ettings are returned on > the next call to > + GetProposedResources(). Before= calling NotifyPhase() > with a Phase of > + EfiPciHostBridgeAllocateResour= ce, the PCI bus > enumerator is responsible > + for gathering I/O and memory r= equests for > + all the PCI root bridges and s= ubmitting these requests > using > + SubmitResources(). This functi= on pads the resource > amount > + to suit the root bridge hardwa= re, takes care of > dependencies between > + the PCI root bridges, and call= s the Global Coherency > Domain (GCD) > + with the allocation request. I= n the case of padding, the > allocated range > + could be bigger than what was = requested. > + EfiPciHostBridgeSetResources Programs the host bridge hardw= are to > decode previously allocated > + resources (proposed resources)= for all the PCI root > bridges. After the > + hardware is programmed, reassi= gning resources will > not be supported. > + The bus settings are not affec= ted. > + EfiPciHostBridgeFreeResources Deallocates resources that wer= e > previously allocated for all the PCI > + root bridges and resets the I/= O and memory apertures > to their initial > + state. The bus settings are no= t affected. If the request > to allocate > + resources fails, the PCI enume= rator can use this > notification to > + deallocate previous resources,= adjust the requests, > and retry > + allocation. > + EfiPciHostBridgeEndResourceAllocation The resource allocation phase = is > completed. No specific action is > + required here. This notificati= on can be used to perform > any chipsetspecific > + programming. > + > + @param[in] PciResAlloc The instance pointer of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > + @param[in] Phase The phase during enumeration > + > + @retval EFI_NOT_READY This phase cannot be entered at this t= ime. > For example, this error > + is valid for a Phase of EfiPciHostBrid= geAllocateResources if > + SubmitResources() has not been called = for one or more > + PCI root bridges before this call > + @retval EFI_DEVICE_ERROR Programming failed due to a hardware > error. This error is valid > + for a Phase of EfiPciHostBridgeSetReso= urces. > + @retval EFI_INVALID_PARAMETER Invalid phase parameter > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + This error is valid for a Phase of > EfiPciHostBridgeAllocateResources if the > + previously submitted resource requests= cannot be fulfilled > or > + were only partially fulfilled. > + @retval EFI_SUCCESS The notification was accepted without = any > errors. > + > +**/ > +EFI_STATUS > +NotifyPhase ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc, > + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase > + ); > + > +/** > + Provides the hooks from the PCI bus driver to every PCI controller > (device/function) at various > + stages of the PCI enumeration process that allow the host bridge drive= r to > preinitialize individual > + PCI controllers before enumeration. > + > + This function is called during the PCI enumeration process. No specifi= c > action is expected from this > + member function. It allows the host bridge driver to preinitialize ind= ividual > PCI controllers before > + enumeration. > + > + @param Bridge Pointer to the > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. > + @param Bus The bus number of the pci device. > + @param Device The device number of the pci device. > + @param Func The function number of the pci device. > + @param Phase The phase of the PCI device enumeration. > + > + @retval EFI_SUCCESS The requested parameters were returne= d. > + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root > bridge handle. > + @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is > defined in > + EFI_PCI_CONTROLLER_RESOURCE_ALLOCATIO= N_PHASE. > + @retval EFI_DEVICE_ERROR Programming failed due to a hardware > error. The PCI enumerator should > + not enumerate this device, including = its child devices if it is > a PCI-to-PCI > + bridge. > + > +**/ > +EFI_STATUS > +PreprocessController ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func, > + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase > + ); > + > +/** > + This function allows the PCI bus driver to be notified to act as reque= sted > when a hot-plug event has > + happened on the hot-plug controller. Currently, the operations include > add operation and remove operation.. > + > + @param This A pointer to the hot plug request protocol= . > + @param Operation The operation the PCI bus driver is reques= ted to > make. > + @param Controller The handle of the hot-plug controller. > + @param RemainingDevicePath The remaining device path for the PCI-like > hot-plug device. > + @param NumberOfChildren The number of child handles. > + For a add operation, it is an output param= eter. > + For a remove operation, it's an input para= meter. > + @param ChildHandleBuffer The buffer which contains the child handle= s. > + > + @retval EFI_INVALID_PARAMETER Operation is not a legal value. > + Controller is NULL or not a valid handl= e. > + NumberOfChildren is NULL. > + ChildHandleBuffer is NULL while Operati= on is add. > + @retval EFI_OUT_OF_RESOURCES There are no enough resources to start > the devices. > + @retval EFI_NOT_FOUND Can not find bridge according to contro= ller > handle. > + @retval EFI_SUCCESS The handles for the specified device ha= ve been > created or destroyed > + as requested, and for an add operation,= the new handles > are > + returned in ChildHandleBuffer. > +**/ > +EFI_STATUS > +EFIAPI > +PciHotPlugRequestNotify ( > + IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This, > + IN EFI_PCI_HOTPLUG_OPERATION Operation, > + IN EFI_HANDLE Controller, > + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL, > + IN OUT UINT8 *NumberOfChildren, > + IN OUT EFI_HANDLE * ChildHandleBuffer > + ); > + > +/** > + Search hostbridge according to given handle > + > + @param RootBridgeHandle Host bridge handle. > + > + @retval TRUE Found host bridge handle. > + @retval FALSE Not found hot bridge handle. > + > +**/ > +BOOLEAN > +SearchHostBridgeHandle ( > + IN EFI_HANDLE RootBridgeHandle > + ); > + > +/** > + Add host bridge handle to global variable for enumerating. > + > + @param HostBridgeHandle Host bridge handle. > + > + @retval EFI_SUCCESS Successfully added host bridge. > + @retval EFI_ABORTED Host bridge is NULL, or given host bridge > + has been in host bridge list. > + > +**/ > +EFI_STATUS > +AddHostBridgeEnumerator ( > + IN EFI_HANDLE HostBridgeHandle > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumeratorSupport.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumeratorSupport.c > new file mode 100644 > index 0000000000..99b04a462b > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumeratorSupport.c > @@ -0,0 +1,2885 @@ > +/** @file > + PCI emumeration support functions implementation for PCI Bus module. > + > +Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
> +(C) Copyright 2015 Hewlett Packard Enterprise Development LP
> +Copyright (c) 2021, American Megatrends International LLC.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +extern CHAR16 *mBarTypeStr[]; > +extern EDKII_DEVICE_SECURITY_PROTOCOL > *mDeviceSecurityProtocol; > + > +#define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL > +#define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL > +#define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL > +#define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL > + > +/** > + This routine is used to check whether the pci device is present. > + > + @param PciRootBridgeIo Pointer to instance of > EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. > + @param Pci Output buffer for PCI device configuration sp= ace. > + @param Bus PCI bus NO. > + @param Device PCI device NO. > + @param Func PCI Func NO. > + > + @retval EFI_NOT_FOUND PCI device not present. > + @retval EFI_SUCCESS PCI device is found. > + > +**/ > +EFI_STATUS > +PciDevicePresent ( > + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, > + OUT PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ) > +{ > + UINT64 Address; > + EFI_STATUS Status; > + > + // > + // Create PCI address map in terms of Bus, Device and Func > + // > + Address =3D EFI_PCI_ADDRESS (Bus, Device, Func, 0); > + > + > +//TiogaPass Override START : Skip SPI controller from Enumeration > + > +// > +// > +// It is necessary to skip SPI controller from Enumeration process other= wise > SPI access runing DXE/DXE SMM > +// will causes failures writting to SPI. This is a WA for LBG since curr= ently OS > hidde is not working. > +// > + if(( Bus =3D=3D 0x0) && ( Device =3D=3D 0x1F) && (Func =3D=3D 0x05)){ > + DEBUG ((EFI_D_INFO, "DEBUG - Address - 0x%x BUS %x DEV %x Func %x > SKIP\n", Address, Bus, Device, Func)); > + return EFI_NOT_FOUND; > + } > + > +//TiogaPass Override END > + > + // > + // Read the Vendor ID register > + // > + Status =3D PciRootBridgeIo->Pci.Read ( > + PciRootBridgeIo, > + EfiPciWidthUint32, > + Address, > + 1, > + Pci > + ); > + > + if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId !=3D 0xffff) { > + // > + // Read the entire config header for the device > + // > + Status =3D PciRootBridgeIo->Pci.Read ( > + PciRootBridgeIo, > + EfiPciWidthUint32, > + Address, > + sizeof (PCI_TYPE00) / sizeof (UINT32= ), > + Pci > + ); > + > + return EFI_SUCCESS; > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + Collect all the resource information under this root bridge. > + > + A database that records all the information about pci device subject t= o this > + root bridge will then be created. > + > + @param Bridge Parent bridge instance. > + @param StartBusNumber Bus number of beginning. > + > + @retval EFI_SUCCESS PCI device is found. > + @retval other Some error occurred when reading PCI bridge > information. > + > +**/ > +EFI_STATUS > +PciPciDeviceInfoCollector ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber > + ) > +{ > + EFI_STATUS Status; > + PCI_TYPE00 Pci; > + UINT8 Device; > + UINT8 Func; > + UINT8 SecBus; > + PCI_IO_DEVICE *PciIoDevice; > + EFI_PCI_IO_PROTOCOL *PciIo; > + > + Status =3D EFI_SUCCESS; > + SecBus =3D 0; > + > + for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) { > + > + for (Func =3D 0; Func <=3D PCI_MAX_FUNC; Func++) { > + > + // > + // Check to see whether PCI device is present > + // > + Status =3D PciDevicePresent ( > + Bridge->PciRootBridgeIo, > + &Pci, > + (UINT8) StartBusNumber, > + (UINT8) Device, > + (UINT8) Func > + ); > + > + if (EFI_ERROR (Status) && Func =3D=3D 0) { > + // > + // go to next device if there is no Function 0 > + // > + break; > + } > + > + if (!EFI_ERROR (Status)) { > + > + // > + // Call back to host bridge function > + // > + PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Fu= nc, > EfiPciBeforeResourceCollection); > + > + // > + // Collect all the information about the PCI device discovered > + // > + Status =3D PciSearchDevice ( > + Bridge, > + &Pci, > + (UINT8) StartBusNumber, > + Device, > + Func, > + &PciIoDevice > + ); > + > + // > + // Recursively scan PCI busses on the other side of PCI-PCI brid= ges > + // > + // > + if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || > IS_CARDBUS_BRIDGE (&Pci))) { > + > + // > + // If it is PPB, we need to get the secondary bus to continue = the > enumeration > + // > + PciIo =3D &(PciIoDevice->PciIo); > + > + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, > PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Ensure secondary bus number is greater than the primary bus > number to avoid > + // any potential dead loop when PcdPciDisableBusEnumeration is= set > to TRUE > + // > + if (SecBus <=3D StartBusNumber) { > + break; > + } > + > + // > + // Get resource padding for PPB > + // > + GetResourcePaddingPpb (PciIoDevice); > + > + // > + // Deep enumerate the next level bus > + // > + Status =3D PciPciDeviceInfoCollector ( > + PciIoDevice, > + (UINT8) (SecBus) > + ); > + > + } > + > + if (Func =3D=3D 0 && !IS_PCI_MULTI_FUNC (&Pci)) { > + > + // > + // Skip sub functions, this is not a multi function device > + // > + Func =3D PCI_MAX_FUNC; > + } > + } > + > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Search required device and create PCI device instance. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI bus NO. > + @param Device PCI device NO. > + @param Func PCI func NO. > + @param PciDevice Output of searched PCI device instance. > + > + @retval EFI_SUCCESS Successfully created PCI device instance= . > + @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information. > + > +**/ > +EFI_STATUS > +PciSearchDevice ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func, > + OUT PCI_IO_DEVICE **PciDevice > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D NULL; > + > + DEBUG (( > + EFI_D_INFO, > + "PciBus: Discovered %s @ [%02x|%02x|%02x]\n", > + IS_PCI_BRIDGE (Pci) ? L"PPB" : > + IS_CARDBUS_BRIDGE (Pci) ? L"P2C" : > + L"PCI", > + Bus, Device, Func > + )); > + > + if (!IS_PCI_BRIDGE (Pci)) { > + > + if (IS_CARDBUS_BRIDGE (Pci)) { > + PciIoDevice =3D GatherP2CInfo ( > + Bridge, > + Pci, > + Bus, > + Device, > + Func > + ); > + if ((PciIoDevice !=3D NULL) && gFullEnumeration) { > + InitializeP2C (PciIoDevice); > + } > + } else { > + > + // > + // Create private data for Pci Device > + // > + PciIoDevice =3D GatherDeviceInfo ( > + Bridge, > + Pci, > + Bus, > + Device, > + Func > + ); > + > + } > + > + } else { > + > + // > + // Create private data for PPB > + // > + PciIoDevice =3D GatherPpbInfo ( > + Bridge, > + Pci, > + Bus, > + Device, > + Func > + ); > + > + // > + // Special initialization for PPB including making the PPB quiet > + // > + if ((PciIoDevice !=3D NULL) && gFullEnumeration) { > + InitializePpb (PciIoDevice); > + } > + } > + > + if (PciIoDevice =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Update the bar information for this PCI device so as to support som= e > specific device > + // > + UpdatePciInfo (PciIoDevice); > + > + if (PciIoDevice->DevicePath =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Detect this function has option rom > + // > + if (gFullEnumeration) { > + > + if (!IS_CARDBUS_BRIDGE (Pci)) { > + > + GetOpRomInfo (PciIoDevice); > + > + } > + > + ResetPowerManagementFeature (PciIoDevice); > + > + } > + > + // > + // Insert it into a global tree for future reference > + // > + InsertPciDevice (Bridge, PciIoDevice); > + > + // > + // Determine PCI device attributes > + // > + > + if (PciDevice !=3D NULL) { > + *PciDevice =3D PciIoDevice; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Dump the PPB padding resource information. > + > + @param PciIoDevice PCI IO instance. > + @param ResourceType The desired resource type to dump. > + PciBarTypeUnknown means to dump all types of re= sources. > +**/ > +VOID > +DumpPpbPaddingResource ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN PCI_BAR_TYPE ResourceType > + ) > +{ > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor; > + PCI_BAR_TYPE Type; > + > + if (PciIoDevice->ResourcePaddingDescriptors =3D=3D NULL) { > + return; > + } > + > + if (ResourceType =3D=3D PciBarTypeIo16 || ResourceType =3D=3D PciBarTy= peIo32) { > + ResourceType =3D PciBarTypeIo; > + } > + > + for (Descriptor =3D PciIoDevice->ResourcePaddingDescriptors; Descripto= r- > >Desc !=3D ACPI_END_TAG_DESCRIPTOR; Descriptor++) { > + > + Type =3D PciBarTypeUnknown; > + if (Descriptor->Desc =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR && > Descriptor->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_IO) { > + Type =3D PciBarTypeIo; > + } else if (Descriptor->Desc =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR && > Descriptor->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_MEM) { > + > + if (Descriptor->AddrSpaceGranularity =3D=3D 32) { > + // > + // prefetchable > + // > + if (Descriptor->SpecificFlag =3D=3D > EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABL > E) { > + Type =3D PciBarTypePMem32; > + } > + > + // > + // Non-prefetchable > + // > + if (Descriptor->SpecificFlag =3D=3D 0) { > + Type =3D PciBarTypeMem32; > + } > + } > + > + if (Descriptor->AddrSpaceGranularity =3D=3D 64) { > + // > + // prefetchable > + // > + if (Descriptor->SpecificFlag =3D=3D > EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABL > E) { > + Type =3D PciBarTypePMem64; > + } > + > + // > + // Non-prefetchable > + // > + if (Descriptor->SpecificFlag =3D=3D 0) { > + Type =3D PciBarTypeMem64; > + } > + } > + } > + > + if ((Type !=3D PciBarTypeUnknown) && ((ResourceType =3D=3D > PciBarTypeUnknown) || (ResourceType =3D=3D Type))) { > + DEBUG (( > + EFI_D_INFO, > + " Padding: Type =3D %s; Alignment =3D 0x%lx;\tLength =3D 0x%lx= \n", > + mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen > + )); > + } > + } > + > +} > + > +/** > + Dump the PCI BAR information. > + > + @param PciIoDevice PCI IO instance. > +**/ > +VOID > +DumpPciBars ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + UINTN Index; > + > + for (Index =3D 0; Index < PCI_MAX_BAR; Index++) { > + if (PciIoDevice->PciBar[Index].BarType =3D=3D PciBarTypeUnknown) { > + continue; > + } > + > + DEBUG (( > + EFI_D_INFO, > + " BAR[%d]: Type =3D %s; Alignment =3D 0x%lx;\tLength =3D 0x%lx;\= tOffset =3D > 0x%02x\n", > + Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, > PciBarTypeMaxType)], > + PciIoDevice->PciBar[Index].Alignment, PciIoDevice- > >PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset > + )); > + } > + > + for (Index =3D 0; Index < PCI_MAX_BAR; Index++) { > + if ((PciIoDevice->VfPciBar[Index].BarType =3D=3D PciBarTypeUnknown) = && > (PciIoDevice->VfPciBar[Index].Length =3D=3D 0)) { > + continue; > + } > + > + DEBUG (( > + EFI_D_INFO, > + " VFBAR[%d]: Type =3D %s; Alignment =3D 0x%lx;\tLength =3D 0x%lx;\= tOffset =3D > 0x%02x\n", > + Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, > PciBarTypeMaxType)], > + PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice- > >VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset > + )); > + } > + DEBUG ((EFI_D_INFO, "\n")); > +} > + > +/** > + Create PCI device instance for PCI device. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI device Bus NO. > + @param Device PCI device Device NO. > + @param Func PCI device's func NO. > + > + @return Created PCI device instance. > + > +**/ > +PCI_IO_DEVICE * > +GatherDeviceInfo ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ) > +{ > + UINTN Offset; > + UINTN BarIndex; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D CreatePciIoDevice ( > + Bridge, > + Pci, > + Bus, > + Device, > + Func > + ); > + > + if (PciIoDevice =3D=3D NULL) { > + return NULL; > + } > + > + // > + // If it is a full enumeration, disconnect the device in advance > + // > + if (gFullEnumeration) { > + > + PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, > EFI_PCI_COMMAND_BITS_OWNED); > + > + } > + > + // > + // Start to parse the bars > + // > + for (Offset =3D 0x10, BarIndex =3D 0; Offset <=3D 0x24 && BarIndex < > PCI_MAX_BAR; BarIndex++) { > + Offset =3D PciParseBar (PciIoDevice, Offset, BarIndex); > + } > + > + // > + // Parse the SR-IOV VF bars > + // > + if (PcdGetBool (PcdSrIovSupport) && PciIoDevice->SrIovCapabilityOffset > !=3D 0) { > + for (Offset =3D PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex =3D 0; > + Offset <=3D PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5; > + BarIndex++) { > + > + ASSERT (BarIndex < PCI_MAX_BAR); > + Offset =3D PciIovParseVfBar (PciIoDevice, Offset, BarIndex); > + } > + } > + > + DEBUG_CODE (DumpPciBars (PciIoDevice);); > + return PciIoDevice; > +} > + > +/** > + Create PCI device instance for PCI-PCI bridge. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI device Bus NO. > + @param Device PCI device Device NO. > + @param Func PCI device's func NO. > + > + @return Created PCI device instance. > + > +**/ > +PCI_IO_DEVICE * > +GatherPpbInfo ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + EFI_STATUS Status; > + UINT8 Value; > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT8 Temp; > + UINT32 PMemBaseLimit; > + UINT16 PrefetchableMemoryBase; > + UINT16 PrefetchableMemoryLimit; > + > + PciIoDevice =3D CreatePciIoDevice ( > + Bridge, > + Pci, > + Bus, > + Device, > + Func > + ); > + > + if (PciIoDevice =3D=3D NULL) { > + return NULL; > + } > + > + if (gFullEnumeration) { > + PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, > EFI_PCI_COMMAND_BITS_OWNED); > + > + // > + // Initialize the bridge control register > + // > + PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, > EFI_PCI_BRIDGE_CONTROL_BITS_OWNED); > + > + } > + > + // > + // PPB can have two BARs > + // > + if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) =3D=3D 0x14) { > + // > + // Not 64-bit bar > + // > + PciParseBar (PciIoDevice, 0x14, PPB_BAR_1); > + } > + > + PciIo =3D &PciIoDevice->PciIo; > + > + // > + // Test whether it support 32 decode or not > + // > + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); > + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); > + > + if (Value !=3D 0) { > + if ((Value & 0x01) !=3D 0) { > + PciIoDevice->Decodes |=3D EFI_BRIDGE_IO32_DECODE_SUPPORTED; > + } else { > + PciIoDevice->Decodes |=3D EFI_BRIDGE_IO16_DECODE_SUPPORTED; > + } > + } > + > + // > + // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes > + // PCI bridge supporting non-standard I/O window alignment less than 4= K. > + // > + > + PciIoDevice->BridgeIoAlignment =3D 0xFFF; > + if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) { > + // > + // Check any bits of bit 3-1 of I/O Base Register are writable. > + // if so, it is assumed non-standard I/O window alignment is support= ed by > this bridge. > + // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its = content > can't be assumed. > + // > + Value =3D (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1)); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); > + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); > + Value =3D (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1)); > + switch (Value) { > + case BIT3: > + PciIoDevice->BridgeIoAlignment =3D 0x7FF; > + break; > + case BIT3 | BIT2: > + PciIoDevice->BridgeIoAlignment =3D 0x3FF; > + break; > + case BIT3 | BIT2 | BIT1: > + PciIoDevice->BridgeIoAlignment =3D 0x1FF; > + break; > + } > + } > + > + Status =3D BarExisted ( > + PciIoDevice, > + 0x24, > + NULL, > + &PMemBaseLimit > + ); > + > + // > + // Test if it supports 64 memory or not > + // > + // The bottom 4 bits of both the Prefetchable Memory Base and > Prefetchable Memory Limit > + // registers: > + // 0 - the bridge supports only 32 bit addresses. > + // 1 - the bridge supports 64-bit addresses. > + // > + PrefetchableMemoryBase =3D (UINT16)(PMemBaseLimit & 0xffff); > + PrefetchableMemoryLimit =3D (UINT16)(PMemBaseLimit >> 16); > + if (!EFI_ERROR (Status) && > + (PrefetchableMemoryBase & 0x000f) =3D=3D 0x0001 && > + (PrefetchableMemoryLimit & 0x000f) =3D=3D 0x0001) { > + Status =3D BarExisted ( > + PciIoDevice, > + 0x28, > + NULL, > + NULL > + ); > + > + if (!EFI_ERROR (Status)) { > + PciIoDevice->Decodes |=3D EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; > + PciIoDevice->Decodes |=3D EFI_BRIDGE_PMEM64_DECODE_SUPPORTED; > + } else { > + PciIoDevice->Decodes |=3D EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; > + } > + } > + > + // > + // Memory 32 code is required for ppb > + // > + PciIoDevice->Decodes |=3D EFI_BRIDGE_MEM32_DECODE_SUPPORTED; > + > + GetResourcePaddingPpb (PciIoDevice); > + > + DEBUG_CODE ( > + DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown); > + DumpPciBars (PciIoDevice); > + ); > + > + return PciIoDevice; > +} > + > + > +/** > + Create PCI device instance for PCI Card bridge device. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI device Bus NO. > + @param Device PCI device Device NO. > + @param Func PCI device's func NO. > + > + @return Created PCI device instance. > + > +**/ > +PCI_IO_DEVICE * > +GatherP2CInfo ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D CreatePciIoDevice ( > + Bridge, > + Pci, > + Bus, > + Device, > + Func > + ); > + > + if (PciIoDevice =3D=3D NULL) { > + return NULL; > + } > + > + if (gFullEnumeration) { > + PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, > EFI_PCI_COMMAND_BITS_OWNED); > + > + // > + // Initialize the bridge control register > + // > + PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, > EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED); > + } > + > + // > + // P2C only has one bar that is in 0x10 > + // > + PciParseBar (PciIoDevice, 0x10, P2C_BAR_0); > + > + // > + // Read PciBar information from the bar register > + // > + GetBackPcCardBar (PciIoDevice); > + PciIoDevice->Decodes =3D EFI_BRIDGE_MEM32_DECODE_SUPPORTED | > + EFI_BRIDGE_PMEM32_DECODE_SUPPORTED | > + EFI_BRIDGE_IO32_DECODE_SUPPORTED; > + > + DEBUG_CODE (DumpPciBars (PciIoDevice);); > + > + return PciIoDevice; > +} > + > +/** > + Create device path for pci device. > + > + @param ParentDevicePath Parent bridge's path. > + @param PciIoDevice Pci device instance. > + > + @return Device path protocol instance for specific pci device. > + > +**/ > +EFI_DEVICE_PATH_PROTOCOL * > +CreatePciDevicePath ( > + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + > + PCI_DEVICE_PATH PciNode; > + > + // > + // Create PCI device path > + // > + PciNode.Header.Type =3D HARDWARE_DEVICE_PATH; > + PciNode.Header.SubType =3D HW_PCI_DP; > + SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode)); > + > + PciNode.Device =3D PciIoDevice->DeviceNumber; > + PciNode.Function =3D PciIoDevice->FunctionNumber; > + PciIoDevice->DevicePath =3D AppendDevicePathNode (ParentDevicePath, > &PciNode.Header); > + > + return PciIoDevice->DevicePath; > +} > + > +/** > + Check whether the PCI IOV VF bar is existed or not. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param Offset The offset. > + @param BarLengthValue The bar length value returned. > + @param OriginalBarValue The original bar value returned. > + > + @retval EFI_NOT_FOUND The bar doesn't exist. > + @retval EFI_SUCCESS The bar exist. > + > +**/ > +EFI_STATUS > +VfBarExisted ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + OUT UINT32 *BarLengthValue, > + OUT UINT32 *OriginalBarValue > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT32 OriginalValue; > + UINT32 Value; > + EFI_TPL OldTpl; > + > + // > + // Ensure it is called properly > + // > + ASSERT (PciIoDevice->SrIovCapabilityOffset !=3D 0); > + if (PciIoDevice->SrIovCapabilityOffset =3D=3D 0) { > + return EFI_NOT_FOUND; > + } > + > + PciIo =3D &PciIoDevice->PciIo; > + > + // > + // Preserve the original value > + // > + > + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, > &OriginalValue); > + > + // > + // Raise TPL to high level to disable timer interrupt while the BAR is= probed > + // > + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAll= One); > + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value= ); > + > + // > + // Write back the original value > + // > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, > &OriginalValue); > + > + // > + // Restore TPL to its original level > + // > + gBS->RestoreTPL (OldTpl); > + > + if (BarLengthValue !=3D NULL) { > + *BarLengthValue =3D Value; > + } > + > + if (OriginalBarValue !=3D NULL) { > + *OriginalBarValue =3D OriginalValue; > + } > + > + if (Value =3D=3D 0) { > + return EFI_NOT_FOUND; > + } else { > + return EFI_SUCCESS; > + } > +} > + > +/** > + Check whether the bar is existed or not. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param Offset The offset. > + @param BarLengthValue The bar length value returned. > + @param OriginalBarValue The original bar value returned. > + > + @retval EFI_NOT_FOUND The bar doesn't exist. > + @retval EFI_SUCCESS The bar exist. > + > +**/ > +EFI_STATUS > +BarExisted ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + OUT UINT32 *BarLengthValue, > + OUT UINT32 *OriginalBarValue > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT32 OriginalValue; > + UINT32 Value; > + EFI_TPL OldTpl; > + > + PciIo =3D &PciIoDevice->PciIo; > + > + // > + // Preserve the original value > + // > + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, > &OriginalValue); > + > + // > + // Raise TPL to high level to disable timer interrupt while the BAR is= probed > + // > + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAll= One); > + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value= ); > + > + // > + // Write back the original value > + // > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, > &OriginalValue); > + > + // > + // Restore TPL to its original level > + // > + gBS->RestoreTPL (OldTpl); > + > + if (BarLengthValue !=3D NULL) { > + *BarLengthValue =3D Value; > + } > + > + if (OriginalBarValue !=3D NULL) { > + *OriginalBarValue =3D OriginalValue; > + } > + > + if (Value =3D=3D 0) { > + return EFI_NOT_FOUND; > + } else { > + return EFI_SUCCESS; > + } > +} > + > +/** > + Test whether the device can support given attributes. > + > + @param PciIoDevice Pci device instance. > + @param Command Input command register value, and > + returned supported register value. > + @param BridgeControl Input bridge control value for PPB or P2C, and > + returned supported bridge control value. > + @param OldCommand Returned and stored old command register > offset. > + @param OldBridgeControl Returned and stored old Bridge control value > for PPB or P2C. > + > +**/ > +VOID > +PciTestSupportedAttribute ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN OUT UINT16 *Command, > + IN OUT UINT16 *BridgeControl, > + OUT UINT16 *OldCommand, > + OUT UINT16 *OldBridgeControl > + ) > +{ > + EFI_TPL OldTpl; > + > + // > + // Preserve the original value > + // > + PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand); > + > + // > + // Raise TPL to high level to disable timer interrupt while the BAR is= probed > + // > + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); > + > + PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command); > + PCI_READ_COMMAND_REGISTER (PciIoDevice, Command); > + > + // > + // Write back the original value > + // > + PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand); > + > + // > + // Restore TPL to its original level > + // > + gBS->RestoreTPL (OldTpl); > + > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE > (&PciIoDevice->Pci)) { > + > + // > + // Preserve the original value > + // > + PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl); > + > + // > + // Raise TPL to high level to disable timer interrupt while the BAR = is > probed > + // > + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); > + > + PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl); > + PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl); > + > + // > + // Write back the original value > + // > + PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl); > + > + // > + // Restore TPL to its original level > + // > + gBS->RestoreTPL (OldTpl); > + > + } else { > + *OldBridgeControl =3D 0; > + *BridgeControl =3D 0; > + } > +} > + > +/** > + Set the supported or current attributes of a PCI device. > + > + @param PciIoDevice Structure pointer for PCI device. > + @param Command Command register value. > + @param BridgeControl Bridge control value for PPB or P2C. > + @param Option Make a choice of EFI_SET_SUPPORTS or > EFI_SET_ATTRIBUTES. > + > +**/ > +VOID > +PciSetDeviceAttribute ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT16 Command, > + IN UINT16 BridgeControl, > + IN UINTN Option > + ) > +{ > + UINT64 Attributes; > + > + Attributes =3D 0; > + > + if ((Command & EFI_PCI_COMMAND_IO_SPACE) !=3D 0) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_IO; > + } > + > + if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) !=3D 0) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_MEMORY; > + } > + > + if ((Command & EFI_PCI_COMMAND_BUS_MASTER) !=3D 0) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_BUS_MASTER; > + } > + > + if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) !=3D 0) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; > + } > + > + if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) !=3D 0) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_ISA_IO; > + } > + > + if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) !=3D 0) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_VGA_IO; > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; > + } > + > + if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) !=3D 0) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_VGA_IO_16; > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16; > + } > + > + if (Option =3D=3D EFI_SET_SUPPORTS) { > + > + Attributes |=3D (UINT64) > (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | > + EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | > + EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE | > + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE | > + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM | > + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE); > + > + if (IS_PCI_LPC (&PciIoDevice->Pci)) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO; > + Attributes |=3D (mReserveIsaAliases ? (UINT64) > EFI_PCI_IO_ATTRIBUTE_ISA_IO : \ > + (UINT64) EFI_PCI_IO_ATTRIBUT= E_ISA_IO_16); > + } > + > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE > (&PciIoDevice->Pci)) { > + // > + // For bridge, it should support IDE attributes > + // > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO; > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO; > + > + if (mReserveVgaAliases) { > + Attributes &=3D ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \ > + EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16); > + } else { > + Attributes &=3D ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \ > + EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO); > + } > + } else { > + > + if (IS_PCI_IDE (&PciIoDevice->Pci)) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO; > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO; > + } > + > + if (IS_PCI_VGA (&PciIoDevice->Pci)) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; > + Attributes |=3D (mReserveVgaAliases ? (UINT64) > EFI_PCI_IO_ATTRIBUTE_VGA_IO : \ > + (UINT64) EFI_PCI_IO_ATTRIBUT= E_VGA_IO_16); > + } > + } > + > + PciIoDevice->Supports =3D Attributes; > + PciIoDevice->Supports &=3D ( (PciIoDevice->Parent->Supports) | \ > + EFI_PCI_IO_ATTRIBUTE_IO | > EFI_PCI_IO_ATTRIBUTE_MEMORY | \ > + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER ); > + > + } else { > + // > + // When this attribute is clear, the RomImage and RomSize fields in = the > PCI IO were > + // initialized based on the PCI option ROM found through the ROM BAR= of > the PCI controller. > + // When this attribute is set, the PCI option ROM described by the > RomImage and RomSize > + // fields is not from the the ROM BAR of the PCI controller. > + // > + if (!PciIoDevice->EmbeddedRom) { > + Attributes |=3D EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM; > + } > + PciIoDevice->Attributes =3D Attributes; > + } > +} > + > +/** > + Determine if the device can support Fast Back to Back attribute. > + > + @param PciIoDevice Pci device instance. > + @param StatusIndex Status register value. > + > + @retval EFI_SUCCESS This device support Fast Back to Back attrib= ute. > + @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Bac= k > attribute. > + > +**/ > +EFI_STATUS > +GetFastBackToBackSupport ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 StatusIndex > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + EFI_STATUS Status; > + UINT32 StatusRegister; > + > + // > + // Read the status register > + // > + PciIo =3D &PciIoDevice->PciIo; > + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, = 1, > &StatusRegister); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Check the Fast B2B bit > + // > + if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) !=3D 0) { > + return EFI_SUCCESS; > + } else { > + return EFI_UNSUPPORTED; > + } > +} > + > +/** > + Process the option ROM for all the children of the specified parent PC= I > device. > + It can only be used after the first full Option ROM process. > + > + @param PciIoDevice Pci device instance. > + > +**/ > +VOID > +ProcessOptionRomLight ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + PCI_IO_DEVICE *Temp; > + LIST_ENTRY *CurrentLink; > + > + // > + // For RootBridge, PPB , P2C, go recursively to traverse all its child= ren > + // > + CurrentLink =3D PciIoDevice->ChildList.ForwardLink; > + while (CurrentLink !=3D NULL && CurrentLink !=3D &PciIoDevice->ChildLi= st) { > + > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (!IsListEmpty (&Temp->ChildList)) { > + ProcessOptionRomLight (Temp); > + } > + > + Temp->AllOpRomProcessed =3D PciRomGetImageMapping (Temp); > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > +} > + > +/** > + Determine the related attributes of all devices under a Root Bridge. > + > + @param PciIoDevice PCI device instance. > + > +**/ > +EFI_STATUS > +DetermineDeviceAttribute ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + UINT16 Command; > + UINT16 BridgeControl; > + UINT16 OldCommand; > + UINT16 OldBridgeControl; > + BOOLEAN FastB2BSupport; > + PCI_IO_DEVICE *Temp; > + LIST_ENTRY *CurrentLink; > + EFI_STATUS Status; > + > + // > + // For Root Bridge, just copy it by RootBridgeIo protocol > + // so as to keep consistent with the actual attribute > + // > + if (PciIoDevice->Parent =3D=3D NULL) { > + Status =3D PciIoDevice->PciRootBridgeIo->GetAttributes ( > + PciIoDevice->PciRootBridgeIo= , > + &PciIoDevice->Supports, > + &PciIoDevice->Attributes > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + // > + // Assume the PCI Root Bridge supports DAC > + // > + PciIoDevice->Supports |=3D > (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE | > + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM | > + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE); > + > + } else { > + > + // > + // Set the attributes to be checked for common PCI devices and PPB o= r > P2C > + // Since some devices only support part of them, it is better to set= the > + // attribute according to its command or bridge control register > + // > + Command =3D EFI_PCI_COMMAND_IO_SPACE | > + EFI_PCI_COMMAND_MEMORY_SPACE | > + EFI_PCI_COMMAND_BUS_MASTER | > + EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; > + > + BridgeControl =3D EFI_PCI_BRIDGE_CONTROL_ISA | > EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16; > + > + // > + // Test whether the device can support attributes above > + // > + PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, > &OldCommand, &OldBridgeControl); > + > + // > + // Set the supported attributes for specified PCI device > + // > + PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, > EFI_SET_SUPPORTS); > + > + // > + // Set the current attributes for specified PCI device > + // > + PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, > EFI_SET_ATTRIBUTES); > + > + // > + // Enable other PCI supported attributes but not defined in > PCI_IO_PROTOCOL > + // For PCI Express devices, Memory Write and Invalidate is hardwired= to > 0b so only enable it for PCI devices. > + if (!PciIoDevice->IsPciExp) { > + PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, > EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE); > + } > + } > + > + FastB2BSupport =3D TRUE; > + > + // > + // P2C can not support FB2B on the secondary side > + // > + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { > + FastB2BSupport =3D FALSE; > + } > + > + // > + // For RootBridge, PPB , P2C, go recursively to traverse all its child= ren > + // > + CurrentLink =3D PciIoDevice->ChildList.ForwardLink; > + while (CurrentLink !=3D NULL && CurrentLink !=3D &PciIoDevice->ChildLi= st) { > + > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + Status =3D DetermineDeviceAttribute (Temp); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + // > + // Detect Fast Back to Back support for the device under the bridge > + // > + Status =3D GetFastBackToBackSupport (Temp, > PCI_PRIMARY_STATUS_OFFSET); > + if (FastB2BSupport && EFI_ERROR (Status)) { > + FastB2BSupport =3D FALSE; > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + // > + // Set or clear Fast Back to Back bit for the whole bridge > + // > + if (!IsListEmpty (&PciIoDevice->ChildList)) { > + > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { > + > + Status =3D GetFastBackToBackSupport (PciIoDevice, > PCI_BRIDGE_STATUS_REGISTER_OFFSET); > + > + if (EFI_ERROR (Status) || (!FastB2BSupport)) { > + FastB2BSupport =3D FALSE; > + PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, > EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK); > + } else { > + PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, > EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK); > + } > + } > + > + CurrentLink =3D PciIoDevice->ChildList.ForwardLink; > + while (CurrentLink !=3D NULL && CurrentLink !=3D &PciIoDevice->Child= List) { > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + if (FastB2BSupport) { > + PCI_ENABLE_COMMAND_REGISTER (Temp, > EFI_PCI_COMMAND_FAST_BACK_TO_BACK); > + } else { > + PCI_DISABLE_COMMAND_REGISTER (Temp, > EFI_PCI_COMMAND_FAST_BACK_TO_BACK); > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + } > + // > + // End for IsListEmpty > + // > + return EFI_SUCCESS; > +} > + > +/** > + This routine is used to update the bar information for those incompati= ble > PCI device. > + > + @param PciIoDevice Input Pci device instance. Output Pci device > instance with updated > + Bar information. > + > + @retval EFI_SUCCESS Successfully updated bar information. > + @retval EFI_UNSUPPORTED Given PCI device doesn't belong to > incompatible PCI device list. > + > +**/ > +EFI_STATUS > +UpdatePciInfo ( > + IN OUT PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_STATUS Status; > + UINTN BarIndex; > + BOOLEAN SetFlag; > + VOID *Configuration; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; > + > + Configuration =3D NULL; > + Status =3D EFI_SUCCESS; > + > + if (gIncompatiblePciDeviceSupport =3D=3D NULL) { > + // > + // It can only be supported after the Incompatible PCI Device > + // Support Protocol has been installed > + // > + Status =3D gBS->LocateProtocol ( > + &gEfiIncompatiblePciDeviceSupportProtocolGuid, > + NULL, > + (VOID **) &gIncompatiblePciDeviceSupport > + ); > + } > + if (Status =3D=3D EFI_SUCCESS) { > + // > + // Check whether the device belongs to incompatible devices from > protocol or not > + // If it is , then get its special requirement in the ACPI table > + // > + Status =3D gIncompatiblePciDeviceSupport->CheckDevice ( > + gIncompatiblePciDeviceSu= pport, > + PciIoDevice->Pci.Hdr.Ven= dorId, > + PciIoDevice->Pci.Hdr.Dev= iceId, > + PciIoDevice->Pci.Hdr.Rev= isionID, > + PciIoDevice->Pci.Device.= SubsystemVendorID, > + PciIoDevice->Pci.Device.= SubsystemID, > + &Configuration > + ); > + > + } > + > + if (EFI_ERROR (Status) || Configuration =3D=3D NULL ) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Update PCI device information from the ACPI table > + // > + Ptr =3D (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; > + > + while (Ptr->Desc !=3D ACPI_END_TAG_DESCRIPTOR) { > + > + if (Ptr->Desc !=3D ACPI_ADDRESS_SPACE_DESCRIPTOR) { > + // > + // The format is not support > + // > + break; > + } > + > + for (BarIndex =3D 0; BarIndex < PCI_MAX_BAR; BarIndex++) { > + if ((Ptr->AddrTranslationOffset !=3D MAX_UINT64) && > + (Ptr->AddrTranslationOffset !=3D MAX_UINT8) && > + (Ptr->AddrTranslationOffset !=3D BarIndex) > + ) { > + // > + // Skip updating when AddrTranslationOffset is not MAX_UINT64 or > MAX_UINT8 (wide match). > + // Skip updating when current BarIndex doesn't equal to > AddrTranslationOffset. > + // Comparing against MAX_UINT8 is to keep backward compatibility= . > + // > + continue; > + } > + > + SetFlag =3D FALSE; > + switch (Ptr->ResType) { > + case ACPI_ADDRESS_SPACE_TYPE_MEM: > + > + // > + // Make sure the bar is memory type > + // > + if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem))= { > + SetFlag =3D TRUE; > + > + // > + // Ignored if granularity is 0. > + // Ignored if PCI BAR is I/O or 32-bit memory. > + // If PCI BAR is 64-bit memory and granularity is 32, then > + // the PCI BAR resource is allocated below 4GB. > + // If PCI BAR is 64-bit memory and granularity is 64, then > + // the PCI BAR resource is allocated above 4GB. > + // > + if (PciIoDevice->PciBar[BarIndex].BarType =3D=3D PciBarTypeMem= 64) { > + switch (Ptr->AddrSpaceGranularity) { > + case 32: > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeMem32; > + case 64: > + PciIoDevice->PciBar[BarIndex].BarTypeFixed =3D TRUE; > + break; > + default: > + break; > + } > + } > + > + if (PciIoDevice->PciBar[BarIndex].BarType =3D=3D PciBarTypePMe= m64) { > + switch (Ptr->AddrSpaceGranularity) { > + case 32: > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypePMem32= ; > + case 64: > + PciIoDevice->PciBar[BarIndex].BarTypeFixed =3D TRUE; > + break; > + default: > + break; > + } > + } > + } > + break; > + > + case ACPI_ADDRESS_SPACE_TYPE_IO: > + > + // > + // Make sure the bar is IO type > + // > + if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) = { > + SetFlag =3D TRUE; > + } > + break; > + } > + > + if (SetFlag) { > + > + // > + // Update the new alignment for the device > + // > + SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr- > >AddrRangeMax); > + > + // > + // Update the new length for the device > + // > + if (Ptr->AddrLen !=3D 0) { > + PciIoDevice->PciBar[BarIndex].Length =3D Ptr->AddrLen; > + } > + } > + } > + > + Ptr++; > + } > + > + FreePool (Configuration); > + > + return EFI_SUCCESS; > +} > + > +/** > + This routine will update the alignment with the new alignment. > + Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN > is to keep > + backward compatibility. > + > + @param Alignment Input Old alignment. Output updated alignment. > + @param NewAlignment New alignment. > + > +**/ > +VOID > +SetNewAlign ( > + IN OUT UINT64 *Alignment, > + IN UINT64 NewAlignment > + ) > +{ > + UINT64 OldAlignment; > + UINTN ShiftBit; > + > + // > + // The new alignment is the same as the original, > + // so skip it > + // > + if ((NewAlignment =3D=3D 0) || (NewAlignment =3D=3D OLD_ALIGN)) { > + return ; > + } > + // > + // Check the validity of the parameter > + // > + if (NewAlignment !=3D EVEN_ALIGN && > + NewAlignment !=3D SQUAD_ALIGN && > + NewAlignment !=3D DQUAD_ALIGN ) { > + *Alignment =3D NewAlignment; > + return ; > + } > + > + OldAlignment =3D (*Alignment) + 1; > + ShiftBit =3D 0; > + > + // > + // Get the first non-zero hex value of the length > + // > + while ((OldAlignment & 0x0F) =3D=3D 0x00) { > + OldAlignment =3D RShiftU64 (OldAlignment, 4); > + ShiftBit +=3D 4; > + } > + > + // > + // Adjust the alignment to even, quad or double quad boundary > + // > + if (NewAlignment =3D=3D EVEN_ALIGN) { > + if ((OldAlignment & 0x01) !=3D 0) { > + OldAlignment =3D OldAlignment + 2 - (OldAlignment & 0x01); > + } > + } else if (NewAlignment =3D=3D SQUAD_ALIGN) { > + if ((OldAlignment & 0x03) !=3D 0) { > + OldAlignment =3D OldAlignment + 4 - (OldAlignment & 0x03); > + } > + } else if (NewAlignment =3D=3D DQUAD_ALIGN) { > + if ((OldAlignment & 0x07) !=3D 0) { > + OldAlignment =3D OldAlignment + 8 - (OldAlignment & 0x07); > + } > + } > + > + // > + // Update the old value > + // > + NewAlignment =3D LShiftU64 (OldAlignment, ShiftBit) - 1; > + *Alignment =3D NewAlignment; > + > + return ; > +} > + > +/** > + Parse PCI IOV VF bar information and fill them into PCI device instanc= e. > + > + @param PciIoDevice Pci device instance. > + @param Offset Bar offset. > + @param BarIndex Bar index. > + > + @return Next bar offset. > + > +**/ > +UINTN > +PciIovParseVfBar ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + IN UINTN BarIndex > + ) > +{ > + UINT32 Value; > + UINT32 OriginalValue; > + UINT32 Mask; > + EFI_STATUS Status; > + > + // > + // Ensure it is called properly > + // > + ASSERT (PciIoDevice->SrIovCapabilityOffset !=3D 0); > + if (PciIoDevice->SrIovCapabilityOffset =3D=3D 0) { > + return 0; > + } > + > + OriginalValue =3D 0; > + Value =3D 0; > + > + Status =3D VfBarExisted ( > + PciIoDevice, > + Offset, > + &Value, > + &OriginalValue > + ); > + > + if (EFI_ERROR (Status)) { > + PciIoDevice->VfPciBar[BarIndex].BaseAddress =3D 0; > + PciIoDevice->VfPciBar[BarIndex].Length =3D 0; > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D 0; > + > + // > + // Scan all the BARs anyway > + // > + PciIoDevice->VfPciBar[BarIndex].Offset =3D (UINT16) Offset; > + return Offset + 4; > + } > + > + PciIoDevice->VfPciBar[BarIndex].Offset =3D (UINT16) Offset; > + if ((Value & 0x01) !=3D 0) { > + // > + // Device I/Os. Impossible > + // > + ASSERT (FALSE); > + return Offset + 4; > + > + } else { > + > + Mask =3D 0xfffffff0; > + > + PciIoDevice->VfPciBar[BarIndex].BaseAddress =3D OriginalValue & Mask= ; > + > + switch (Value & 0x07) { > + > + // > + //memory space; anywhere in 32 bit address space > + // > + case 0x00: > + if ((Value & 0x08) !=3D 0) { > + PciIoDevice->VfPciBar[BarIndex].BarType =3D PciBarTypePMem32; > + } else { > + PciIoDevice->VfPciBar[BarIndex].BarType =3D PciBarTypeMem32; > + } > + > + PciIoDevice->VfPciBar[BarIndex].Length =3D (~(Value & Mask)) + = 1; > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >VfPciBar[BarIndex].Length - 1; > + > + // > + // Adjust Length > + // > + PciIoDevice->VfPciBar[BarIndex].Length =3D MultU64x32 (PciIoDevice= - > >VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs); > + // > + // Adjust Alignment > + // > + if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice- > >SystemPageSize - 1) { > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >SystemPageSize - 1; > + } > + > + break; > + > + // > + // memory space; anywhere in 64 bit address space > + // > + case 0x04: > + if ((Value & 0x08) !=3D 0) { > + PciIoDevice->VfPciBar[BarIndex].BarType =3D PciBarTypePMem64; > + } else { > + PciIoDevice->VfPciBar[BarIndex].BarType =3D PciBarTypeMem64; > + } > + > + // > + // According to PCI 2.2,if the bar indicates a memory 64 decoding,= next > bar > + // is regarded as an extension for the first bar. As a result > + // the sizing will be conducted on combined 64 bit value > + // Here just store the masked first 32bit value for future size > + // calculation > + // > + PciIoDevice->VfPciBar[BarIndex].Length =3D Value & Mask; > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >VfPciBar[BarIndex].Length - 1; > + > + if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice- > >SystemPageSize - 1) { > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >SystemPageSize - 1; > + } > + > + // > + // Increment the offset to point to next DWORD > + // > + Offset +=3D 4; > + > + Status =3D VfBarExisted ( > + PciIoDevice, > + Offset, > + &Value, > + &OriginalValue > + ); > + > + if (EFI_ERROR (Status)) { > + PciIoDevice->VfPciBar[BarIndex].BarType =3D PciBarTypeUnknown; > + return Offset + 4; > + } > + > + // > + // Fix the length to support some special 64 bit BAR > + // > + Value |=3D ((UINT32) -1 << HighBitSet32 (Value)); > + > + // > + // Calculate the size of 64bit bar > + // > + PciIoDevice->VfPciBar[BarIndex].BaseAddress |=3D LShiftU64 ((UINT6= 4) > OriginalValue, 32); > + > + PciIoDevice->VfPciBar[BarIndex].Length =3D PciIoDevice- > >VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32); > + PciIoDevice->VfPciBar[BarIndex].Length =3D (~(PciIoDevice- > >VfPciBar[BarIndex].Length)) + 1; > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >VfPciBar[BarIndex].Length - 1; > + > + // > + // Adjust Length > + // > + PciIoDevice->VfPciBar[BarIndex].Length =3D MultU64x32 (PciIoDevice= - > >VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs); > + // > + // Adjust Alignment > + // > + if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice- > >SystemPageSize - 1) { > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >SystemPageSize - 1; > + } > + > + break; > + > + // > + // reserved > + // > + default: > + PciIoDevice->VfPciBar[BarIndex].BarType =3D PciBarTypeUnknown; > + PciIoDevice->VfPciBar[BarIndex].Length =3D (~(Value & Mask)) + = 1; > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >VfPciBar[BarIndex].Length - 1; > + > + if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice- > >SystemPageSize - 1) { > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice- > >SystemPageSize - 1; > + } > + > + break; > + } > + } > + > + // > + // Check the length again so as to keep compatible with some special b= ars > + // > + if (PciIoDevice->VfPciBar[BarIndex].Length =3D=3D 0) { > + PciIoDevice->VfPciBar[BarIndex].BarType =3D PciBarTypeUnknown; > + PciIoDevice->VfPciBar[BarIndex].BaseAddress =3D 0; > + PciIoDevice->VfPciBar[BarIndex].Alignment =3D 0; > + } > + > + // > + // Increment number of bar > + // > + return Offset + 4; > +} > + > +/** > + Parse PCI bar information and fill them into PCI device instance. > + > + @param PciIoDevice Pci device instance. > + @param Offset Bar offset. > + @param BarIndex Bar index. > + > + @return Next bar offset. > + > +**/ > +UINTN > +PciParseBar ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + IN UINTN BarIndex > + ) > +{ > + UINT32 Value; > + UINT32 OriginalValue; > + UINT32 Mask; > + EFI_STATUS Status; > + > + OriginalValue =3D 0; > + Value =3D 0; > + > + Status =3D BarExisted ( > + PciIoDevice, > + Offset, > + &Value, > + &OriginalValue > + ); > + > + if (EFI_ERROR (Status)) { > + PciIoDevice->PciBar[BarIndex].BaseAddress =3D 0; > + PciIoDevice->PciBar[BarIndex].Length =3D 0; > + PciIoDevice->PciBar[BarIndex].Alignment =3D 0; > + > + // > + // Some devices don't fully comply to PCI spec 2.2. So be to scan al= l the > BARs anyway > + // > + PciIoDevice->PciBar[BarIndex].Offset =3D (UINT8) Offset; > + return Offset + 4; > + } > + > + PciIoDevice->PciBar[BarIndex].BarTypeFixed =3D FALSE; > + PciIoDevice->PciBar[BarIndex].Offset =3D (UINT8) Offset; > + if ((Value & 0x01) !=3D 0) { > + // > + // Device I/Os > + // > + Mask =3D 0xfffffffc; > + > + if ((Value & 0xFFFF0000) !=3D 0) { > + // > + // It is a IO32 bar > + // > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeIo32; > + PciIoDevice->PciBar[BarIndex].Length =3D ((~(Value & Mask)) + 1= ); > + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice- > >PciBar[BarIndex].Length - 1; > + > + } else { > + // > + // It is a IO16 bar > + // > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeIo16; > + PciIoDevice->PciBar[BarIndex].Length =3D 0x0000FFFF & ((~(Value= & > Mask)) + 1); > + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice- > >PciBar[BarIndex].Length - 1; > + > + } > + // > + // Workaround. Some platforms implement IO bar with 0 length > + // Need to treat it as no-bar > + // > + if (PciIoDevice->PciBar[BarIndex].Length =3D=3D 0) { > + PciIoDevice->PciBar[BarIndex].BarType =3D (PCI_BAR_TYPE) 0; > + } > + > + PciIoDevice->PciBar[BarIndex].BaseAddress =3D OriginalValue & Mask= ; > + > + } else { > + > + Mask =3D 0xfffffff0; > + > + PciIoDevice->PciBar[BarIndex].BaseAddress =3D OriginalValue & Mask; > + > + switch (Value & 0x07) { > + > + // > + //memory space; anywhere in 32 bit address space > + // > + case 0x00: > + if ((Value & 0x08) !=3D 0) { > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypePMem32; > + } else { > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeMem32; > + } > + > + PciIoDevice->PciBar[BarIndex].Length =3D (~(Value & Mask)) + 1; > + if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) { > + // > + // Force minimum 4KByte alignment for Virtualization technology = for > Directed I/O > + // > + PciIoDevice->PciBar[BarIndex].Alignment =3D (SIZE_4KB - 1); > + } else { > + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice- > >PciBar[BarIndex].Length - 1; > + } > + break; > + > + // > + // memory space; anywhere in 64 bit address space > + // > + case 0x04: > + if ((Value & 0x08) !=3D 0) { > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypePMem64; > + } else { > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeMem64; > + } > + > + // > + // According to PCI 2.2,if the bar indicates a memory 64 decoding,= next > bar > + // is regarded as an extension for the first bar. As a result > + // the sizing will be conducted on combined 64 bit value > + // Here just store the masked first 32bit value for future size > + // calculation > + // > + PciIoDevice->PciBar[BarIndex].Length =3D Value & Mask; > + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice- > >PciBar[BarIndex].Length - 1; > + > + // > + // Increment the offset to point to next DWORD > + // > + Offset +=3D 4; > + > + Status =3D BarExisted ( > + PciIoDevice, > + Offset, > + &Value, > + &OriginalValue > + ); > + > + if (EFI_ERROR (Status)) { > + // > + // the high 32 bit does not claim any BAR, we need to re-check t= he low > 32 bit BAR again > + // > + if (PciIoDevice->PciBar[BarIndex].Length =3D=3D 0) { > + // > + // some device implement MMIO bar with 0 length, need to treat= it as > no-bar > + // > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeUnknown; > + return Offset + 4; > + } > + } > + > + // > + // Fix the length to support some special 64 bit BAR > + // > + if (Value =3D=3D 0) { > + DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM6= 4 > BAR returns 0, change to 0xFFFFFFFF.\n")); > + Value =3D (UINT32) -1; > + } else { > + Value |=3D ((UINT32)(-1) << HighBitSet32 (Value)); > + } > + > + // > + // Calculate the size of 64bit bar > + // > + PciIoDevice->PciBar[BarIndex].BaseAddress |=3D LShiftU64 ((UINT64) > OriginalValue, 32); > + > + PciIoDevice->PciBar[BarIndex].Length =3D PciIoDevice- > >PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32); > + PciIoDevice->PciBar[BarIndex].Length =3D (~(PciIoDevice- > >PciBar[BarIndex].Length)) + 1; > + if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) { > + // > + // Force minimum 4KByte alignment for Virtualization technology = for > Directed I/O > + // > + PciIoDevice->PciBar[BarIndex].Alignment =3D (SIZE_4KB - 1); > + } else { > + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice- > >PciBar[BarIndex].Length - 1; > + } > + > + break; > + > + // > + // reserved > + // > + default: > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeUnknown; > + PciIoDevice->PciBar[BarIndex].Length =3D (~(Value & Mask)) + 1; > + if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) { > + // > + // Force minimum 4KByte alignment for Virtualization technology = for > Directed I/O > + // > + PciIoDevice->PciBar[BarIndex].Alignment =3D (SIZE_4KB - 1); > + } else { > + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice- > >PciBar[BarIndex].Length - 1; > + } > + break; > + } > + } > + > + // > + // Check the length again so as to keep compatible with some special b= ars > + // > + if (PciIoDevice->PciBar[BarIndex].Length =3D=3D 0) { > + PciIoDevice->PciBar[BarIndex].BarType =3D PciBarTypeUnknown; > + PciIoDevice->PciBar[BarIndex].BaseAddress =3D 0; > + PciIoDevice->PciBar[BarIndex].Alignment =3D 0; > + } > + > + // > + // Increment number of bar > + // > + return Offset + 4; > +} > + > +/** > + This routine is used to initialize the bar of a PCI device. > + > + @param PciIoDevice Pci device instance. > + > + @note It can be called typically when a device is going to be rejected= . > + > +**/ > +VOID > +InitializePciDevice ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT8 Offset; > + > + PciIo =3D &(PciIoDevice->PciIo); > + > + // > + // Put all the resource apertures > + // Resource base is set to all ones so as to indicate its resource > + // has not been allocated > + // > + for (Offset =3D 0x10; Offset <=3D 0x24; Offset +=3D sizeof (UINT32)) { > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne); > + } > +} > + > +/** > + This routine is used to initialize the bar of a PCI-PCI Bridge device. > + > + @param PciIoDevice PCI-PCI bridge device instance. > + > +**/ > +VOID > +InitializePpb ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + > + PciIo =3D &(PciIoDevice->PciIo); > + > + // > + // Put all the resource apertures including IO16 > + // Io32, pMem32, pMem64 to quiescent state > + // Resource base all ones, Resource limit all zeros > + // > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero); > + > + // > + // Don't support use io32 as for now > + // > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero); > + > + // > + // Force Interrupt line to zero for cards that come up randomly > + // > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); > +} > + > +/** > + This routine is used to initialize the bar of a PCI Card Bridge device= . > + > + @param PciIoDevice PCI Card bridge device. > + > +**/ > +VOID > +InitializeP2C ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + > + PciIo =3D &(PciIoDevice->PciIo); > + > + // > + // Put all the resource apertures including IO16 > + // Io32, pMem32, pMem64 to quiescent state( > + // Resource base all ones, Resource limit all zeros > + // > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero); > + > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero); > + > + // > + // Force Interrupt line to zero for cards that come up randomly > + // > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); > +} > + > +/** > + Authenticate the PCI device by using DeviceSecurityProtocol. > + > + @param PciIoDevice PCI device. > + > + @retval EFI_SUCCESS The device passes the authentication. > + @return not EFI_SUCCESS The device failes the authentication or > + unexpected error happen during authentication. > +**/ > +EFI_STATUS > +AuthenticatePciDevice ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EDKII_DEVICE_IDENTIFIER DeviceIdentifier; > + EFI_STATUS Status; > + > + if (mDeviceSecurityProtocol !=3D NULL) { > + // > + // Prepare the parameter > + // > + DeviceIdentifier.Version =3D EDKII_DEVICE_IDENTIFIER_REVISION; > + CopyGuid (&DeviceIdentifier.DeviceType, > &gEdkiiDeviceIdentifierTypePciGuid); > + DeviceIdentifier.DeviceHandle =3D NULL; > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &DeviceIdentifier.DeviceHandle, > + &gEfiDevicePathProtocolGuid, > + PciIoDevice->DevicePath, > + &gEdkiiDeviceIdentifierTypePciGuid, > + &PciIoDevice->PciIo, > + NULL > + ); > + if (EFI_ERROR(Status)) { > + return Status; > + } > + > + // > + // Do DeviceAuthentication > + // > + Status =3D mDeviceSecurityProtocol->DeviceAuthenticate > (mDeviceSecurityProtocol, &DeviceIdentifier); > + // > + // Always uninstall, because they are only for Authentication. > + // No need to check return Status. > + // > + gBS->UninstallMultipleProtocolInterfaces ( > + DeviceIdentifier.DeviceHandle, > + &gEfiDevicePathProtocolGuid, > + PciIoDevice->DevicePath, > + &gEdkiiDeviceIdentifierTypePciGuid, > + &PciIoDevice->PciIo, > + NULL > + ); > + return Status; > + } > + > + // > + // Device Security Protocol is not found, just return success > + // > + return EFI_SUCCESS; > +} > + > +/** > + Create and initialize general PCI I/O device instance for > + PCI device/bridge device/hotplug bridge device. > + > + @param Bridge Parent bridge instance. > + @param Pci Input Pci information block. > + @param Bus Device Bus NO. > + @param Device Device device NO. > + @param Func Device func NO. > + > + @return Instance of PCI device. NULL means no instance created. > + > +**/ > +PCI_IO_DEVICE * > +CreatePciIoDevice ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + EFI_PCI_IO_PROTOCOL *PciIo; > + EFI_STATUS Status; > + > + PciIoDevice =3D AllocateZeroPool (sizeof (PCI_IO_DEVICE)); > + if (PciIoDevice =3D=3D NULL) { > + return NULL; > + } > + > + PciIoDevice->Signature =3D PCI_IO_DEVICE_SIGNATURE; > + PciIoDevice->Handle =3D NULL; > + PciIoDevice->PciRootBridgeIo =3D Bridge->PciRootBridgeIo; > + PciIoDevice->DevicePath =3D NULL; > + PciIoDevice->BusNumber =3D Bus; > + PciIoDevice->DeviceNumber =3D Device; > + PciIoDevice->FunctionNumber =3D Func; > + PciIoDevice->Decodes =3D 0; > + > + if (gFullEnumeration) { > + PciIoDevice->Allocated =3D FALSE; > + } else { > + PciIoDevice->Allocated =3D TRUE; > + } > + > + PciIoDevice->Registered =3D FALSE; > + PciIoDevice->Attributes =3D 0; > + PciIoDevice->Supports =3D 0; > + PciIoDevice->BusOverride =3D FALSE; > + PciIoDevice->AllOpRomProcessed =3D FALSE; > + > + PciIoDevice->IsPciExp =3D FALSE; > + > + CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01)); > + > + // > + // Initialize the PCI I/O instance structure > + // > + InitializePciIoInstance (PciIoDevice); > + InitializePciDriverOverrideInstance (PciIoDevice); > + InitializePciLoadFile2 (PciIoDevice); > + PciIo =3D &PciIoDevice->PciIo; > + > + // > + // Create a device path for this PCI device and store it into its priv= ate data > + // > + CreatePciDevicePath ( > + Bridge->DevicePath, > + PciIoDevice > + ); > + > + // > + // Detect if PCI Express Device > + // > + PciIoDevice->PciExpressCapabilityOffset =3D 0; > + Status =3D LocateCapabilityRegBlock ( > + PciIoDevice, > + EFI_PCI_CAPABILITY_ID_PCIEXP, > + &PciIoDevice->PciExpressCapabilityOffset, > + NULL > + ); > + if (!EFI_ERROR (Status)) { > + PciIoDevice->IsPciExp =3D TRUE; > + } > + > + // > + // Now we can do the authentication check for the device. > + // > + Status =3D AuthenticatePciDevice (PciIoDevice); > + // > + // If authentication fails, skip this device. > + // > + if (EFI_ERROR(Status)) { > + if (PciIoDevice->DevicePath !=3D NULL) { > + FreePool (PciIoDevice->DevicePath); > + } > + FreePool (PciIoDevice); > + return NULL; > + } > + > + if (PcdGetBool (PcdAriSupport)) { > + // > + // Check if the device is an ARI device. > + // > + Status =3D LocatePciExpressCapabilityRegBlock ( > + PciIoDevice, > + EFI_PCIE_CAPABILITY_ID_ARI, > + &PciIoDevice->AriCapabilityOffset, > + NULL > + ); > + if (!EFI_ERROR (Status)) { > + // > + // We need to enable ARI feature before calculate BusReservation, > + // because FirstVFOffset and VFStride may change after that. > + // > + EFI_PCI_IO_PROTOCOL *ParentPciIo; > + UINT32 Data32; > + > + // > + // Check if its parent supports ARI forwarding. > + // > + ParentPciIo =3D &Bridge->PciIo; > + ParentPciIo->Pci.Read ( > + ParentPciIo, > + EfiPciIoWidthUint32, > + Bridge->PciExpressCapabilityOffset + > EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, > + 1, > + &Data32 > + ); > + if ((Data32 & > EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) !=3D 0) { > + // > + // ARI forward support in bridge, so enable it. > + // > + ParentPciIo->Pci.Read ( > + ParentPciIo, > + EfiPciIoWidthUint32, > + Bridge->PciExpressCapabilityOffset + > EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, > + 1, > + &Data32 > + ); > + if ((Data32 & > EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) =3D=3D 0) { > + Data32 |=3D > EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING; > + ParentPciIo->Pci.Write ( > + ParentPciIo, > + EfiPciIoWidthUint32, > + Bridge->PciExpressCapabilityOffset + > EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, > + 1, > + &Data32 > + ); > + DEBUG (( > + EFI_D_INFO, > + " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n", > + Bridge->BusNumber, > + Bridge->DeviceNumber, > + Bridge->FunctionNumber > + )); > + } > + } > + > + DEBUG ((EFI_D_INFO, " ARI: CapOffset =3D 0x%x\n", PciIoDevice- > >AriCapabilityOffset)); > + } > + } > + > + // > + // Initialization for SR-IOV > + // > + > + if (PcdGetBool (PcdSrIovSupport)) { > + Status =3D LocatePciExpressCapabilityRegBlock ( > + PciIoDevice, > + EFI_PCIE_CAPABILITY_ID_SRIOV, > + &PciIoDevice->SrIovCapabilityOffset, > + NULL > + ); > + if (!EFI_ERROR (Status)) { > + UINT32 SupportedPageSize; > + UINT16 VFStride; > + UINT16 FirstVFOffset; > + UINT16 Data16; > + UINT32 PFRid; > + UINT32 LastVF; > + > + // > + // If the SR-IOV device is an ARI device, then Set ARI Capable Hie= rarchy > for the device. > + // > + if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset= !=3D 0) > { > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, > + 1, > + &Data16 > + ); > + Data16 |=3D EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, > + 1, > + &Data16 > + ); > + } > + > + // > + // Calculate SystemPageSize > + // > + > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint32, > + PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE, > + 1, > + &SupportedPageSize > + ); > + PciIoDevice->SystemPageSize =3D (PcdGet32 (PcdSrIovSystemPageSize)= & > SupportedPageSize); > + ASSERT (PciIoDevice->SystemPageSize !=3D 0); > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE, > + 1, > + &PciIoDevice->SystemPageSize > + ); > + // > + // Adjust SystemPageSize for Alignment usage later > + // > + PciIoDevice->SystemPageSize <<=3D 12; > + > + // > + // Calculate BusReservation for PCI IOV > + // > + > + // > + // Read First FirstVFOffset, InitialVFs, and VFStride > + // > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF, > + 1, > + &FirstVFOffset > + ); > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS, > + 1, > + &PciIoDevice->InitialVFs > + ); > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PciIoDevice->SrIovCapabilityOffset + > EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE, > + 1, > + &VFStride > + ); > + // > + // Calculate LastVF > + // > + PFRid =3D EFI_PCI_RID(Bus, Device, Func); > + LastVF =3D PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) *= VFStride; > + > + // > + // Calculate ReservedBusNum for this PF > + // > + PciIoDevice->ReservedBusNum =3D (UINT16)(EFI_PCI_BUS_OF_RID > (LastVF) - Bus + 1); > + > + DEBUG (( > + EFI_D_INFO, > + " SR-IOV: SupportedPageSize =3D 0x%x; SystemPageSize =3D 0x%x; > FirstVFOffset =3D 0x%x;\n", > + SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOff= set > + )); > + DEBUG (( > + EFI_D_INFO, > + " InitialVFs =3D 0x%x; ReservedBusNum =3D 0x%x; CapOffse= t =3D 0x%x\n", > + PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevic= e- > >SrIovCapabilityOffset > + )); > + } > + } > + > + if (PcdGetBool (PcdMrIovSupport)) { > + Status =3D LocatePciExpressCapabilityRegBlock ( > + PciIoDevice, > + EFI_PCIE_CAPABILITY_ID_MRIOV, > + &PciIoDevice->MrIovCapabilityOffset, > + NULL > + ); > + if (!EFI_ERROR (Status)) { > + DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset =3D 0x%x\n", PciIoDevice- > >MrIovCapabilityOffset)); > + } > + } > + > + PciIoDevice->ResizableBarOffset =3D 0; > + if (PcdGetBool (PcdPcieResizableBarSupport)) { > + Status =3D LocatePciExpressCapabilityRegBlock ( > + PciIoDevice, > + PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID, > + &PciIoDevice->ResizableBarOffset, > + NULL > + ); > + if (!EFI_ERROR (Status)) { > + PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL > ResizableBarControl; > + UINT32 Offset; > + Offset =3D PciIoDevice->ResizableBarOffset + sizeof > (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER) > + + sizeof > (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY), > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint8, > + Offset, > + sizeof > (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL), > + &ResizableBarControl > + ); > + PciIoDevice->ResizableBarNumber =3D > ResizableBarControl.Bits.ResizableBarNumber; > + PciProgramResizableBar (PciIoDevice, PciResizableBarMax); > + } > + } > + > + // > + // Initialize the reserved resource list > + // > + InitializeListHead (&PciIoDevice->ReservedResourceList); > + > + // > + // Initialize the driver list > + // > + InitializeListHead (&PciIoDevice->OptionRomDriverList); > + > + // > + // Initialize the child list > + // > + InitializeListHead (&PciIoDevice->ChildList); > + > + return PciIoDevice; > +} > + > +/** > + This routine is used to enumerate entire pci bus system > + in a given platform. > + > + It is only called on the second start on the same Root Bridge. > + > + @param Controller Parent bridge handler. > + > + @retval EFI_SUCCESS PCI enumeration finished successfully. > + @retval other Some error occurred when enumerating the pci bu= s > system. > + > +**/ > +EFI_STATUS > +PciEnumeratorLight ( > + IN EFI_HANDLE Controller > + ) > +{ > + > + EFI_STATUS Status; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + PCI_IO_DEVICE *RootBridgeDev; > + UINT16 MinBus; > + UINT16 MaxBus; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; > + > + MinBus =3D 0; > + MaxBus =3D PCI_MAX_BUS; > + Descriptors =3D NULL; > + > + // > + // If this root bridge has been already enumerated, then return > successfully > + // > + if (GetRootBridgeByHandle (Controller) !=3D NULL) { > + return EFI_SUCCESS; > + } > + > + // > + // Open pci root bridge io protocol > + // > + Status =3D gBS->OpenProtocol ( > + Controller, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo, > + gPciBusDriverBinding.DriverBindingHandle, > + Controller, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + if (EFI_ERROR (Status) && Status !=3D EFI_ALREADY_STARTED) { > + return Status; > + } > + > + Status =3D PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) > &Descriptors); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) =3D=3D > EFI_SUCCESS) { > + > + // > + // Create a device node for root bridge device with a NULL host brid= ge > controller handle > + // > + RootBridgeDev =3D CreateRootBridge (Controller); > + > + if (RootBridgeDev =3D=3D NULL) { > + Descriptors++; > + continue; > + } > + > + // > + // Record the root bridge-io protocol > + // > + RootBridgeDev->PciRootBridgeIo =3D PciRootBridgeIo; > + > + Status =3D PciPciDeviceInfoCollector ( > + RootBridgeDev, > + (UINT8) MinBus > + ); > + > + if (!EFI_ERROR (Status)) { > + > + // > + // Remove those PCI devices which are rejected when full enumerati= on > + // > + RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev); > + > + // > + // Process option rom light > + // > + ProcessOptionRomLight (RootBridgeDev); > + > + // > + // Determine attributes for all devices under this root bridge > + // > + DetermineDeviceAttribute (RootBridgeDev); > + > + // > + // If successfully, insert the node into device pool > + // > + InsertRootBridge (RootBridgeDev); > + } else { > + > + // > + // If unsuccessfully, destroy the entire node > + // > + DestroyRootBridge (RootBridgeDev); > + } > + > + Descriptors++; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Get bus range from PCI resource descriptor list. > + > + @param Descriptors A pointer to the address space descriptor. > + @param MinBus The min bus returned. > + @param MaxBus The max bus returned. > + @param BusRange The bus range returned. > + > + @retval EFI_SUCCESS Successfully got bus range. > + @retval EFI_NOT_FOUND Can not find the specific bus. > + > +**/ > +EFI_STATUS > +PciGetBusRange ( > + IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, > + OUT UINT16 *MinBus, > + OUT UINT16 *MaxBus, > + OUT UINT16 *BusRange > + ) > +{ > + while ((*Descriptors)->Desc !=3D ACPI_END_TAG_DESCRIPTOR) { > + if ((*Descriptors)->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_BUS) { > + if (MinBus !=3D NULL) { > + *MinBus =3D (UINT16) (*Descriptors)->AddrRangeMin; > + } > + > + if (MaxBus !=3D NULL) { > + *MaxBus =3D (UINT16) (*Descriptors)->AddrRangeMax; > + } > + > + if (BusRange !=3D NULL) { > + *BusRange =3D (UINT16) (*Descriptors)->AddrLen; > + } > + > + return EFI_SUCCESS; > + } > + > + (*Descriptors)++; > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This routine can be used to start the root bridge. > + > + @param RootBridgeDev Pci device instance. > + > + @retval EFI_SUCCESS This device started. > + @retval other Failed to get PCI Root Bridge I/O protocol. > + > +**/ > +EFI_STATUS > +StartManagingRootBridge ( > + IN PCI_IO_DEVICE *RootBridgeDev > + ) > +{ > + EFI_HANDLE RootBridgeHandle; > + EFI_STATUS Status; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + > + // > + // Get the root bridge handle > + // > + RootBridgeHandle =3D RootBridgeDev->Handle; > + PciRootBridgeIo =3D NULL; > + > + // > + // Get the pci root bridge io protocol > + // > + Status =3D gBS->OpenProtocol ( > + RootBridgeHandle, > + &gEfiPciRootBridgeIoProtocolGuid, > + (VOID **) &PciRootBridgeIo, > + gPciBusDriverBinding.DriverBindingHandle, > + RootBridgeHandle, > + EFI_OPEN_PROTOCOL_BY_DRIVER > + ); > + > + if (EFI_ERROR (Status) && Status !=3D EFI_ALREADY_STARTED) { > + return Status; > + } > + > + // > + // Store the PciRootBridgeIo protocol into root bridge private data > + // > + RootBridgeDev->PciRootBridgeIo =3D PciRootBridgeIo; > + > + return EFI_SUCCESS; > + > +} > + > +/** > + This routine can be used to check whether a PCI device should be rejec= ted > when light enumeration. > + > + @param PciIoDevice Pci device instance. > + > + @retval TRUE This device should be rejected. > + @retval FALSE This device shouldn't be rejected. > + > +**/ > +BOOLEAN > +IsPciDeviceRejected ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_STATUS Status; > + UINT32 TestValue; > + UINT32 OldValue; > + UINT32 Mask; > + UINT8 BarOffset; > + > + // > + // PPB should be skip! > + // > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { > + return FALSE; > + } > + > + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { > + // > + // Only test base registers for P2C > + // > + for (BarOffset =3D 0x1C; BarOffset <=3D 0x38; BarOffset +=3D 2 * siz= eof > (UINT32)) { > + > + Mask =3D (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC; > + Status =3D BarExisted (PciIoDevice, BarOffset, &TestValue, &OldVa= lue); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + TestValue =3D TestValue & Mask; > + if ((TestValue !=3D 0) && (TestValue =3D=3D (OldValue & Mask))) { > + // > + // The bar isn't programed, so it should be rejected > + // > + return TRUE; > + } > + } > + > + return FALSE; > + } > + > + for (BarOffset =3D 0x14; BarOffset <=3D 0x24; BarOffset +=3D sizeof (U= INT32)) { > + // > + // Test PCI devices > + // > + Status =3D BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue= ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + if ((TestValue & 0x01) !=3D 0) { > + > + // > + // IO Bar > + // > + Mask =3D 0xFFFFFFFC; > + TestValue =3D TestValue & Mask; > + if ((TestValue !=3D 0) && (TestValue =3D=3D (OldValue & Mask))) { > + return TRUE; > + } > + > + } else { > + > + // > + // Mem Bar > + // > + Mask =3D 0xFFFFFFF0; > + TestValue =3D TestValue & Mask; > + > + if ((TestValue & 0x07) =3D=3D 0x04) { > + > + // > + // Mem64 or PMem64 > + // > + BarOffset +=3D sizeof (UINT32); > + if ((TestValue !=3D 0) && (TestValue =3D=3D (OldValue & Mask))) = { > + > + // > + // Test its high 32-Bit BAR > + // > + Status =3D BarExisted (PciIoDevice, BarOffset, &TestValue, &Ol= dValue); > + if (TestValue =3D=3D OldValue) { > + return TRUE; > + } > + } > + > + } else { > + > + // > + // Mem32 or PMem32 > + // > + if ((TestValue !=3D 0) && (TestValue =3D=3D (OldValue & Mask))) = { > + return TRUE; > + } > + } > + } > + } > + > + return FALSE; > +} > + > +/** > + Reset all bus number from specific bridge. > + > + @param Bridge Parent specific bridge. > + @param StartBusNumber Start bus number. > + > +**/ > +VOID > +ResetAllPpbBusNumber ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber > + ) > +{ > + EFI_STATUS Status; > + PCI_TYPE00 Pci; > + UINT8 Device; > + UINT32 Register; > + UINT8 Func; > + UINT64 Address; > + UINT8 SecondaryBus; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + > + PciRootBridgeIo =3D Bridge->PciRootBridgeIo; > + > + for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) { > + for (Func =3D 0; Func <=3D PCI_MAX_FUNC; Func++) { > + > + // > + // Check to see whether a pci device is present > + // > + Status =3D PciDevicePresent ( > + PciRootBridgeIo, > + &Pci, > + StartBusNumber, > + Device, > + Func > + ); > + > + if (EFI_ERROR (Status) && Func =3D=3D 0) { > + // > + // go to next device if there is no Function 0 > + // > + break; > + } > + > + if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) { > + > + Register =3D 0; > + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1= 8); > + Status =3D PciRootBridgeIo->Pci.Read ( > + PciRootBridgeIo, > + EfiPciWidthUint32, > + Address, > + 1, > + &Register > + ); > + SecondaryBus =3D (UINT8)(Register >> 8); > + > + if (SecondaryBus !=3D 0) { > + ResetAllPpbBusNumber (Bridge, SecondaryBus); > + } > + > + // > + // Reset register 18h, 19h, 1Ah on PCI Bridge > + // > + Register &=3D 0xFF000000; > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint32, > + Address, > + 1, > + &Register > + ); > + } > + > + if (Func =3D=3D 0 && !IS_PCI_MULTI_FUNC (&Pci)) { > + // > + // Skip sub functions, this is not a multi function device > + // > + Func =3D PCI_MAX_FUNC; > + } > + } > + } > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumeratorSupport.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumeratorSupport.h > new file mode 100644 > index 0000000000..1d39c5171d > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciEnumeratorSupport.h > @@ -0,0 +1,480 @@ > +/** @file > + PCI enumeration support functions declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H_ > +#define _EFI_PCI_ENUMERATOR_SUPPORT_H_ > + > +/** > + This routine is used to check whether the pci device is present. > + > + @param PciRootBridgeIo Pointer to instance of > EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. > + @param Pci Output buffer for PCI device configuration sp= ace. > + @param Bus PCI bus NO. > + @param Device PCI device NO. > + @param Func PCI Func NO. > + > + @retval EFI_NOT_FOUND PCI device not present. > + @retval EFI_SUCCESS PCI device is found. > + > +**/ > +EFI_STATUS > +PciDevicePresent ( > + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, > + OUT PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ); > + > +/** > + Collect all the resource information under this root bridge. > + > + A database that records all the information about pci device subject t= o this > + root bridge will then be created. > + > + @param Bridge Parent bridge instance. > + @param StartBusNumber Bus number of beginning. > + > + @retval EFI_SUCCESS PCI device is found. > + @retval other Some error occurred when reading PCI bridge > information. > + > +**/ > +EFI_STATUS > +PciPciDeviceInfoCollector ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber > + ); > + > +/** > + Search required device and create PCI device instance. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI bus NO. > + @param Device PCI device NO. > + @param Func PCI func NO. > + @param PciDevice Output of searched PCI device instance. > + > + @retval EFI_SUCCESS Successfully created PCI device instance= . > + @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information. > + > +**/ > +EFI_STATUS > +PciSearchDevice ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func, > + OUT PCI_IO_DEVICE **PciDevice > + ); > + > +/** > + Create PCI device instance for PCI device. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI device Bus NO. > + @param Device PCI device Device NO. > + @param Func PCI device's func NO. > + > + @return Created PCI device instance. > + > +**/ > +PCI_IO_DEVICE * > +GatherDeviceInfo ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ); > + > +/** > + Create PCI device instance for PCI-PCI bridge. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI device Bus NO. > + @param Device PCI device Device NO. > + @param Func PCI device's func NO. > + > + @return Created PCI device instance. > + > +**/ > +PCI_IO_DEVICE * > +GatherPpbInfo ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ); > + > +/** > + Create PCI device instance for PCI Card bridge device. > + > + @param Bridge Parent bridge instance. > + @param Pci Input PCI device information block. > + @param Bus PCI device Bus NO. > + @param Device PCI device Device NO. > + @param Func PCI device's func NO. > + > + @return Created PCI device instance. > + > +**/ > +PCI_IO_DEVICE * > +GatherP2CInfo ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ); > + > +/** > + Create device path for pci device. > + > + @param ParentDevicePath Parent bridge's path. > + @param PciIoDevice Pci device instance. > + > + @return Device path protocol instance for specific pci device. > + > +**/ > +EFI_DEVICE_PATH_PROTOCOL * > +CreatePciDevicePath ( > + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Check whether the PCI IOV VF bar is existed or not. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param Offset The offset. > + @param BarLengthValue The bar length value returned. > + @param OriginalBarValue The original bar value returned. > + > + @retval EFI_NOT_FOUND The bar doesn't exist. > + @retval EFI_SUCCESS The bar exist. > + > +**/ > +EFI_STATUS > +VfBarExisted ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + OUT UINT32 *BarLengthValue, > + OUT UINT32 *OriginalBarValue > + ); > + > +/** > + Check whether the bar is existed or not. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param Offset The offset. > + @param BarLengthValue The bar length value returned. > + @param OriginalBarValue The original bar value returned. > + > + @retval EFI_NOT_FOUND The bar doesn't exist. > + @retval EFI_SUCCESS The bar exist. > + > +**/ > +EFI_STATUS > +BarExisted ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + OUT UINT32 *BarLengthValue, > + OUT UINT32 *OriginalBarValue > + ); > + > +/** > + Test whether the device can support given attributes. > + > + @param PciIoDevice Pci device instance. > + @param Command Input command register value, and > + returned supported register value. > + @param BridgeControl Input bridge control value for PPB or P2C, and > + returned supported bridge control value. > + @param OldCommand Returned and stored old command register > offset. > + @param OldBridgeControl Returned and stored old Bridge control value > for PPB or P2C. > + > +**/ > +VOID > +PciTestSupportedAttribute ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN OUT UINT16 *Command, > + IN OUT UINT16 *BridgeControl, > + OUT UINT16 *OldCommand, > + OUT UINT16 *OldBridgeControl > + ); > + > +/** > + Set the supported or current attributes of a PCI device. > + > + @param PciIoDevice Structure pointer for PCI device. > + @param Command Command register value. > + @param BridgeControl Bridge control value for PPB or P2C. > + @param Option Make a choice of EFI_SET_SUPPORTS or > EFI_SET_ATTRIBUTES. > + > +**/ > +VOID > +PciSetDeviceAttribute ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT16 Command, > + IN UINT16 BridgeControl, > + IN UINTN Option > + ); > + > +/** > + Determine if the device can support Fast Back to Back attribute. > + > + @param PciIoDevice Pci device instance. > + @param StatusIndex Status register value. > + > + @retval EFI_SUCCESS This device support Fast Back to Back attrib= ute. > + @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Bac= k > attribute. > + > +**/ > +EFI_STATUS > +GetFastBackToBackSupport ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 StatusIndex > + ); > + > +/** > + Determine the related attributes of all devices under a Root Bridge. > + > + @param PciIoDevice PCI device instance. > + > +**/ > +EFI_STATUS > +DetermineDeviceAttribute ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + This routine is used to update the bar information for those incompati= ble > PCI device. > + > + @param PciIoDevice Input Pci device instance. Output Pci device > instance with updated > + Bar information. > + > + @retval EFI_SUCCESS Successfully updated bar information. > + @retval EFI_UNSUPPORTED Given PCI device doesn't belong to > incompatible PCI device list. > + > +**/ > +EFI_STATUS > +UpdatePciInfo ( > + IN OUT PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + This routine will update the alignment with the new alignment. > + > + @param Alignment Input Old alignment. Output updated alignment. > + @param NewAlignment New alignment. > + > +**/ > +VOID > +SetNewAlign ( > + IN OUT UINT64 *Alignment, > + IN UINT64 NewAlignment > + ); > + > +/** > + Parse PCI bar information and fill them into PCI device instance. > + > + @param PciIoDevice Pci device instance. > + @param Offset Bar offset. > + @param BarIndex Bar index. > + > + @return Next bar offset. > + > +**/ > +UINTN > +PciParseBar ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + IN UINTN BarIndex > + ); > + > +/** > + Parse PCI IOV VF bar information and fill them into PCI device instanc= e. > + > + @param PciIoDevice Pci device instance. > + @param Offset Bar offset. > + @param BarIndex Bar index. > + > + @return Next bar offset. > + > +**/ > +UINTN > +PciIovParseVfBar ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINTN Offset, > + IN UINTN BarIndex > + ); > + > +/** > + This routine is used to initialize the bar of a PCI device. > + > + @param PciIoDevice Pci device instance. > + > + @note It can be called typically when a device is going to be rejected= . > + > +**/ > +VOID > +InitializePciDevice ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + This routine is used to initialize the bar of a PCI-PCI Bridge device. > + > + @param PciIoDevice PCI-PCI bridge device instance. > + > +**/ > +VOID > +InitializePpb ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + This routine is used to initialize the bar of a PCI Card Bridge device= . > + > + @param PciIoDevice PCI Card bridge device. > + > +**/ > +VOID > +InitializeP2C ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Create and initialize general PCI I/O device instance for > + PCI device/bridge device/hotplug bridge device. > + > + @param Bridge Parent bridge instance. > + @param Pci Input Pci information block. > + @param Bus Device Bus NO. > + @param Device Device device NO. > + @param Func Device func NO. > + > + @return Instance of PCI device. NULL means no instance created. > + > +**/ > +PCI_IO_DEVICE * > +CreatePciIoDevice ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_TYPE00 *Pci, > + IN UINT8 Bus, > + IN UINT8 Device, > + IN UINT8 Func > + ); > + > +/** > + This routine is used to enumerate entire pci bus system > + in a given platform. > + > + It is only called on the second start on the same Root Bridge. > + > + @param Controller Parent bridge handler. > + > + @retval EFI_SUCCESS PCI enumeration finished successfully. > + @retval other Some error occurred when enumerating the pci bu= s > system. > + > +**/ > +EFI_STATUS > +PciEnumeratorLight ( > + IN EFI_HANDLE Controller > + ); > + > +/** > + Get bus range from PCI resource descriptor list. > + > + @param Descriptors A pointer to the address space descriptor. > + @param MinBus The min bus returned. > + @param MaxBus The max bus returned. > + @param BusRange The bus range returned. > + > + @retval EFI_SUCCESS Successfully got bus range. > + @retval EFI_NOT_FOUND Can not find the specific bus. > + > +**/ > +EFI_STATUS > +PciGetBusRange ( > + IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, > + OUT UINT16 *MinBus, > + OUT UINT16 *MaxBus, > + OUT UINT16 *BusRange > + ); > + > +/** > + This routine can be used to start the root bridge. > + > + @param RootBridgeDev Pci device instance. > + > + @retval EFI_SUCCESS This device started. > + @retval other Failed to get PCI Root Bridge I/O protocol. > + > +**/ > +EFI_STATUS > +StartManagingRootBridge ( > + IN PCI_IO_DEVICE *RootBridgeDev > + ); > + > +/** > + This routine can be used to check whether a PCI device should be rejec= ted > when light enumeration. > + > + @param PciIoDevice Pci device instance. > + > + @retval TRUE This device should be rejected. > + @retval FALSE This device shouldn't be rejected. > + > +**/ > +BOOLEAN > +IsPciDeviceRejected ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Reset all bus number from specific bridge. > + > + @param Bridge Parent specific bridge. > + @param StartBusNumber Start bus number. > + > +**/ > +VOID > +ResetAllPpbBusNumber ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber > + ); > + > +/** > + Dump the PPB padding resource information. > + > + @param PciIoDevice PCI IO instance. > + @param ResourceType The desired resource type to dump. > + PciBarTypeUnknown means to dump all types of re= sources. > +**/ > +VOID > +DumpPpbPaddingResource ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN PCI_BAR_TYPE ResourceType > + ); > + > +/** > + Dump the PCI BAR information. > + > + @param PciIoDevice PCI IO instance. > +**/ > +VOID > +DumpPciBars ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciHotPlugSupport.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciHotPlugSupport.c > new file mode 100644 > index 0000000000..d6d06b061a > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciHotPlugSupport.c > @@ -0,0 +1,484 @@ > +/** @file > + PCI Hot Plug support functions implementation for PCI Bus module.. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit =3D NULL; > +EFI_HPC_LOCATION *gPciRootHpcPool =3D NULL; > +UINTN gPciRootHpcCount =3D 0; > +ROOT_HPC_DATA *gPciRootHpcData =3D NULL; > + > + > +/** > + Event notification function to set Hot Plug controller status. > + > + @param Event The event that invoke this function. > + @param Context The calling context, pointer to > ROOT_HPC_DATA. > + > +**/ > +VOID > +EFIAPI > +PciHPCInitialized ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + ROOT_HPC_DATA *HpcData; > + > + HpcData =3D (ROOT_HPC_DATA *) Context; > + HpcData->Initialized =3D TRUE; > +} > + > +/** > + Compare two device paths to check if they are exactly same. > + > + @param DevicePath1 A pointer to the first device path data structur= e. > + @param DevicePath2 A pointer to the second device path data structu= re. > + > + @retval TRUE They are same. > + @retval FALSE They are not same. > + > +**/ > +BOOLEAN > +EfiCompareDevicePath ( > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 > + ) > +{ > + UINTN Size1; > + UINTN Size2; > + > + Size1 =3D GetDevicePathSize (DevicePath1); > + Size2 =3D GetDevicePathSize (DevicePath2); > + > + if (Size1 !=3D Size2) { > + return FALSE; > + } > + > + if (CompareMem (DevicePath1, DevicePath2, Size1) !=3D 0) { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + Check hot plug support and initialize root hot plug private data. > + > + If Hot Plug is supported by the platform, call PCI Hot Plug Init proto= col > + to get PCI Hot Plug controller's information and constructor the root = hot > plug > + private data structure. > + > + @retval EFI_SUCCESS They are same. > + @retval EFI_UNSUPPORTED No PCI Hot Plug controller on the platfo= rm. > + @retval EFI_OUT_OF_RESOURCES No memory to constructor root hot > plug private > + data structure. > + > +**/ > +EFI_STATUS > +InitializeHotPlugSupport ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + EFI_HPC_LOCATION *HpcList; > + UINTN HpcCount; > + > + // > + // Locate the PciHotPlugInit Protocol > + // If it doesn't exist, that means there is no > + // hot plug controller supported on the platform > + // the PCI Bus driver is running on. HotPlug Support > + // is an optional feature, so absence of the protocol > + // won't incur the penalty. > + // > + Status =3D gBS->LocateProtocol ( > + &gEfiPciHotPlugInitProtocolGuid, > + NULL, > + (VOID **) &gPciHotPlugInit > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + Status =3D gPciHotPlugInit->GetRootHpcList ( > + gPciHotPlugInit, > + &HpcCount, > + &HpcList > + ); > + > + if (!EFI_ERROR (Status)) { > + > + gPciRootHpcPool =3D HpcList; > + gPciRootHpcCount =3D HpcCount; > + gPciRootHpcData =3D AllocateZeroPool (sizeof (ROOT_HPC_DATA) * > gPciRootHpcCount); > + if (gPciRootHpcData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Test whether device path is for root pci hot plug bus. > + > + @param HpbDevicePath A pointer to device path data structure to be > tested. > + @param HpIndex If HpIndex is not NULL, return the index of root= hot > + plug in global array when TRUE is returned. > + > + @retval TRUE The device path is for root pci hot plug bus. > + @retval FALSE The device path is not for root pci hot plug bus= . > + > +**/ > +BOOLEAN > +IsRootPciHotPlugBus ( > + IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath, > + OUT UINTN *HpIndex OPTIONAL > + ) > +{ > + UINTN Index; > + > + for (Index =3D 0; Index < gPciRootHpcCount; Index++) { > + > + if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, > HpbDevicePath)) { > + > + if (HpIndex !=3D NULL) { > + *HpIndex =3D Index; > + } > + > + return TRUE; > + } > + } > + > + return FALSE; > +} > + > +/** > + Test whether device path is for root pci hot plug controller. > + > + @param HpcDevicePath A pointer to device path data structure to be > tested. > + @param HpIndex If HpIndex is not NULL, return the index of root= hot > + plug in global array when TRUE is returned. > + > + @retval TRUE The device path is for root pci hot plug control= ler. > + @retval FALSE The device path is not for root pci hot plug con= troller. > + > +**/ > +BOOLEAN > +IsRootPciHotPlugController ( > + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, > + OUT UINTN *HpIndex > + ) > +{ > + UINTN Index; > + > + for (Index =3D 0; Index < gPciRootHpcCount; Index++) { > + > + if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, > HpcDevicePath)) { > + > + if (HpIndex !=3D NULL) { > + *HpIndex =3D Index; > + } > + > + return TRUE; > + } > + } > + > + return FALSE; > +} > + > +/** > + Creating event object for PCI Hot Plug controller. > + > + @param HpIndex Index of hot plug device in global array. > + @param Event The returned event that invoke this function. > + > + @return Status of create event. > + > +**/ > +EFI_STATUS > +CreateEventForHpc ( > + IN UINTN HpIndex, > + OUT EFI_EVENT *Event > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D gBS->CreateEvent ( > + EVT_NOTIFY_SIGNAL, > + TPL_CALLBACK, > + PciHPCInitialized, > + gPciRootHpcData + HpIndex, > + &((gPciRootHpcData + HpIndex)->Event) > + ); > + > + if (!EFI_ERROR (Status)) { > + *Event =3D (gPciRootHpcData + HpIndex)->Event; > + } > + > + return Status; > +} > + > +/** > + Wait for all root PCI Hot Plug controller finished initializing. > + > + @param TimeoutInMicroSeconds Microseconds to wait for all root HPCs' > initialization. > + > + @retval EFI_SUCCESS All HPCs initialization finished. > + @retval EFI_TIMEOUT Not ALL HPCs initialization finished in > Microseconds. > + > +**/ > +EFI_STATUS > +AllRootHPCInitialized ( > + IN UINTN TimeoutInMicroSeconds > + ) > +{ > + UINT32 Delay; > + UINTN Index; > + > + Delay =3D (UINT32) ((TimeoutInMicroSeconds / 30) + 1); > + > + do { > + for (Index =3D 0; Index < gPciRootHpcCount; Index++) { > + > + if (gPciRootHpcData[Index].Found && > !gPciRootHpcData[Index].Initialized) { > + break; > + } > + } > + > + if (Index =3D=3D gPciRootHpcCount) { > + return EFI_SUCCESS; > + } > + > + // > + // Stall for 30 microseconds.. > + // > + gBS->Stall (30); > + > + Delay--; > + > + } while (Delay > 0); > + > + return EFI_TIMEOUT; > +} > + > +/** > + Check whether PCI-PCI bridge has PCI Hot Plug capability register bloc= k. > + > + @param PciIoDevice A Pointer to the PCI-PCI bridge. > + > + @retval TRUE PCI device is HPC. > + @retval FALSE PCI device is not HPC. > + > +**/ > +BOOLEAN > +IsSHPC ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + > + EFI_STATUS Status; > + UINT8 Offset; > + > + if (PciIoDevice =3D=3D NULL) { > + return FALSE; > + } > + > + Offset =3D 0; > + Status =3D LocateCapabilityRegBlock ( > + PciIoDevice, > + EFI_PCI_CAPABILITY_ID_SHPC, > + &Offset, > + NULL > + ); > + > + // > + // If the PCI-PCI bridge has the hot plug controller build-in, > + // then return TRUE; > + // > + if (!EFI_ERROR (Status)) { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + Check whether PciIoDevice supports PCIe hotplug. > + > + This is equivalent to the following condition: > + - the device is either a PCIe switch downstream port or a root port, > + - and the device has the SlotImplemented bit set in its PCIe capabilit= y > + register, > + - and the device has the HotPlugCapable bit set in its slot capabiliti= es > + register. > + > + @param[in] PciIoDevice The device being checked. > + > + @retval TRUE PciIoDevice is a PCIe port that accepts a hot-plugged d= evice. > + @retval FALSE Otherwise. > + > +**/ > +BOOLEAN > +SupportsPcieHotplug ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + UINT32 Offset; > + EFI_STATUS Status; > + PCI_REG_PCIE_CAPABILITY Capability; > + PCI_REG_PCIE_SLOT_CAPABILITY SlotCapability; > + > + if (PciIoDevice =3D=3D NULL) { > + return FALSE; > + } > + > + // > + // Read the PCI Express Capabilities Register > + // > + if (!PciIoDevice->IsPciExp) { > + return FALSE; > + } > + Offset =3D PciIoDevice->PciExpressCapabilityOffset + > + OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability); > + Status =3D PciIoDevice->PciIo.Pci.Read ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint16, > + Offset, > + 1, > + &Capability > + ); > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + // > + // Check the contents of the register > + // > + switch (Capability.Bits.DevicePortType) { > + case PCIE_DEVICE_PORT_TYPE_ROOT_PORT: > + case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT: > + break; > + default: > + return FALSE; > + } > + if (!Capability.Bits.SlotImplemented) { > + return FALSE; > + } > + > + // > + // Read the Slot Capabilities Register > + // > + Offset =3D PciIoDevice->PciExpressCapabilityOffset + > + OFFSET_OF (PCI_CAPABILITY_PCIEXP, SlotCapability); > + Status =3D PciIoDevice->PciIo.Pci.Read ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint32, > + Offset, > + 1, > + &SlotCapability > + ); > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + // > + // Check the contents of the register > + // > + if (SlotCapability.Bits.HotPlugCapable) { > + return TRUE; > + } > + return FALSE; > +} > + > +/** > + Get resource padding if the specified PCI bridge is a hot plug bus. > + > + @param PciIoDevice PCI bridge instance. > + > +**/ > +VOID > +GetResourcePaddingForHpb ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_STATUS Status; > + EFI_HPC_STATE State; > + UINT64 PciAddress; > + EFI_HPC_PADDING_ATTRIBUTES Attributes; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; > + > + if (IsPciHotPlugBus (PciIoDevice)) { > + // > + // If PCI-PCI bridge device is PCI Hot Plug bus. > + // > + PciAddress =3D EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice- > >DeviceNumber, PciIoDevice->FunctionNumber, 0); > + Status =3D gPciHotPlugInit->GetResourcePadding ( > + gPciHotPlugInit, > + PciIoDevice->DevicePath, > + PciAddress, > + &State, > + (VOID **) &Descriptors, > + &Attributes > + ); > + > + if (EFI_ERROR (Status)) { > + return; > + } > + > + if ((State & EFI_HPC_STATE_ENABLED) !=3D 0 && (State & > EFI_HPC_STATE_INITIALIZED) !=3D 0) { > + PciIoDevice->ResourcePaddingDescriptors =3D Descriptors; > + PciIoDevice->PaddingAttributes =3D Attributes; > + } > + > + return; > + } > +} > + > +/** > + Test whether PCI device is hot plug bus. > + > + @param PciIoDevice PCI device instance. > + > + @retval TRUE PCI device is a hot plug bus. > + @retval FALSE PCI device is not a hot plug bus. > + > +**/ > +BOOLEAN > +IsPciHotPlugBus ( > + PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + if (IsSHPC (PciIoDevice)) { > + // > + // If the PPB has the hot plug controller build-in, > + // then return TRUE; > + // > + return TRUE; > + } > + > + if (SupportsPcieHotplug (PciIoDevice)) { > + // > + // If the PPB is a PCIe root complex port or a switch downstream por= t, and > + // implements a hot-plug capable slot, then also return TRUE. > + // > + return TRUE; > + } > + > + // > + // Otherwise, see if it is a Root HPC > + // > + if(IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL)) { > + return TRUE; > + } > + > + return FALSE; > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciHotPlugSupport.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciHotPlugSupport.h > new file mode 100644 > index 0000000000..0b69237a3d > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciHotPlugSupport.h > @@ -0,0 +1,205 @@ > +/** @file > + PCI Hot Plug support functions declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_HOT_PLUG_SUPPORT_H_ > +#define _EFI_PCI_HOT_PLUG_SUPPORT_H_ > + > +// > +// stall 1 second, its unit is 100ns > +// > +#define STALL_1_SECOND 1000000 > + > +// > +// PCI Hot Plug controller private data > +// > +typedef struct { > + EFI_EVENT Event; > + BOOLEAN Found; > + BOOLEAN Initialized; > + VOID *Padding; > +} ROOT_HPC_DATA; > + > +// > +// Reference of some global variables > +// > +extern EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit; > +extern EFI_HPC_LOCATION *gPciRootHpcPool; > +extern ROOT_HPC_DATA *gPciRootHpcData; > + > +/** > + Event notification function to set Hot Plug controller status. > + > + @param Event The event that invoke this function. > + @param Context The calling context, pointer to > ROOT_HPC_DATA. > + > +**/ > +VOID > +EFIAPI > +PciHPCInitialized ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ); > + > +/** > + Compare two device paths to check if they are exactly same. > + > + @param DevicePath1 A pointer to the first device path data structur= e. > + @param DevicePath2 A pointer to the second device path data structu= re. > + > + @retval TRUE They are same. > + @retval FALSE They are not same. > + > +**/ > +BOOLEAN > +EfiCompareDevicePath ( > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 > + ); > + > +/** > + Check hot plug support and initialize root hot plug private data. > + > + If Hot Plug is supported by the platform, call PCI Hot Plug Init proto= col > + to get PCI Hot Plug controller's information and constructor the root = hot > plug > + private data structure. > + > + @retval EFI_SUCCESS They are same. > + @retval EFI_UNSUPPORTED No PCI Hot Plug controller on the platfo= rm. > + @retval EFI_OUT_OF_RESOURCES No memory to constructor root hot > plug private > + data structure. > + > +**/ > +EFI_STATUS > +InitializeHotPlugSupport ( > + VOID > + ); > + > +/** > + Test whether PCI device is hot plug bus. > + > + @param PciIoDevice PCI device instance. > + > + @retval TRUE PCI device is a hot plug bus. > + @retval FALSE PCI device is not a hot plug bus. > + > +**/ > +BOOLEAN > +IsPciHotPlugBus ( > + PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Test whether device path is for root pci hot plug bus. > + > + @param HpbDevicePath A pointer to device path data structure to be > tested. > + @param HpIndex If HpIndex is not NULL, return the index of root= hot > + plug in global array when TRUE is returned. > + > + @retval TRUE The device path is for root pci hot plug bus. > + @retval FALSE The device path is not for root pci hot plug bus= . > + > +**/ > +BOOLEAN > +IsRootPciHotPlugBus ( > + IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath, > + OUT UINTN *HpIndex OPTIONAL > + ); > + > +/** > + Test whether device path is for root pci hot plug controller. > + > + @param HpcDevicePath A pointer to device path data structure to be > tested. > + @param HpIndex If HpIndex is not NULL, return the index of root= hot > + plug in global array when TRUE is returned. > + > + @retval TRUE The device path is for root pci hot plug control= ler. > + @retval FALSE The device path is not for root pci hot plug con= troller. > + > +**/ > +BOOLEAN > +IsRootPciHotPlugController ( > + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, > + OUT UINTN *HpIndex > + ); > + > +/** > + Creating event object for PCI Hot Plug controller. > + > + @param HpIndex Index of hot plug device in global array. > + @param Event The returned event that invoke this function. > + > + @return Status of create event. > + > +**/ > +EFI_STATUS > +CreateEventForHpc ( > + IN UINTN HpIndex, > + OUT EFI_EVENT *Event > + ); > + > +/** > + Wait for all root PCI Hot Plug controller finished initializing. > + > + @param TimeoutInMicroSeconds Microseconds to wait for all root HPCs' > initialization. > + > + @retval EFI_SUCCESS All HPCs initialization finished. > + @retval EFI_TIMEOUT Not ALL HPCs initialization finished in > Microseconds. > + > +**/ > +EFI_STATUS > +AllRootHPCInitialized ( > + IN UINTN TimeoutInMicroSeconds > + ); > + > +/** > + Check whether PCI-PCI bridge has PCI Hot Plug capability register bloc= k. > + > + @param PciIoDevice A Pointer to the PCI-PCI bridge. > + > + @retval TRUE PCI device is HPC. > + @retval FALSE PCI device is not HPC. > + > +**/ > +BOOLEAN > +IsSHPC ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Check whether PciIoDevice supports PCIe hotplug. > + > + This is equivalent to the following condition: > + - the device is either a PCIe switch downstream port or a root port, > + - and the device has the SlotImplemented bit set in its PCIe capabilit= y > + register, > + - and the device has the HotPlugCapable bit set in its slot capabiliti= es > + register. > + > + @param[in] PciIoDevice The device being checked. > + > + @retval TRUE PciIoDevice is a PCIe port that accepts a hot-plugged d= evice. > + @retval FALSE Otherwise. > + > +**/ > +BOOLEAN > +SupportsPcieHotplug ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Get resource padding if the specified PCI bridge is a hot plug bus. > + > + @param PciIoDevice PCI bridge instance. > + > +**/ > +VOID > +GetResourcePaddingForHpb ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciIo.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciIo.c > new file mode 100644 > index 0000000000..c656056315 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciIo.c > @@ -0,0 +1,2087 @@ > +/** @file > + EFI PCI IO protocol functions implementation for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; > + > +// > +// Pci Io Protocol Interface > +// > +EFI_PCI_IO_PROTOCOL mPciIoInterface =3D { > + PciIoPollMem, > + PciIoPollIo, > + { > + PciIoMemRead, > + PciIoMemWrite > + }, > + { > + PciIoIoRead, > + PciIoIoWrite > + }, > + { > + PciIoConfigRead, > + PciIoConfigWrite > + }, > + PciIoCopyMem, > + PciIoMap, > + PciIoUnmap, > + PciIoAllocateBuffer, > + PciIoFreeBuffer, > + PciIoFlush, > + PciIoGetLocation, > + PciIoAttributes, > + PciIoGetBarAttributes, > + PciIoSetBarAttributes, > + 0, > + NULL > +}; > + > +/** > + Initializes a PCI I/O Instance. > + > + @param PciIoDevice Pci device instance. > + > +**/ > +VOID > +InitializePciIoInstance ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + CopyMem (&PciIoDevice->PciIo, &mPciIoInterface, sizeof > (EFI_PCI_IO_PROTOCOL)); > +} > + > +/** > + Verifies access to a PCI Base Address Register (BAR). > + > + @param PciIoDevice Pci device instance. > + @param BarIndex The BAR index of the standard PCI Configuration > header to use as the > + base address for the memory or I/O operation to pe= rform. > + @param Type Operation type could be memory or I/O. > + @param Width Signifies the width of the memory or I/O operation= s. > + @param Count The number of memory or I/O operations to perform. > + @param Offset The offset within the PCI configuration space for = the PCI > controller. > + > + @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type. > + @retval EFI_SUCCESS Successfully verified. > + > +**/ > +EFI_STATUS > +PciIoVerifyBarAccess ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 BarIndex, > + IN PCI_BAR_TYPE Type, > + IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN IN UINTN Count, > + IN UINT64 *Offset > + ) > +{ > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (BarIndex =3D=3D EFI_PCI_IO_PASS_THROUGH_BAR) { > + return EFI_SUCCESS; > + } > + > + // > + // BarIndex 0-5 is legal > + // > + if (BarIndex >=3D PCI_MAX_BAR) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (!CheckBarType (PciIoDevice, BarIndex, Type)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUin= tX > + // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUin= tX > + // > + if (Width >=3D EfiPciIoWidthFifoUint8 && Width <=3D EfiPciIoWidthFifoU= int64) { > + Count =3D 1; > + } > + > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03); > + > + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >=3D PciIoDevice- > >PciBar[BarIndex].Length) { > + return EFI_INVALID_PARAMETER; > + } > + > + *Offset =3D *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress; > + > + return EFI_SUCCESS; > +} > + > +/** > + Verifies access to a PCI Configuration Header. > + > + @param PciIoDevice Pci device instance. > + @param Width Signifies the width of the memory or I/O operation= s. > + @param Count The number of memory or I/O operations to perform. > + @param Offset The offset within the PCI configuration space for = the PCI > controller. > + > + @retval EFI_INVALID_PARAMETER Invalid Width > + @retval EFI_UNSUPPORTED Offset overflowed. > + @retval EFI_SUCCESS Successfully verified. > + > +**/ > +EFI_STATUS > +PciIoVerifyConfigAccess ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINTN Count, > + IN UINT64 *Offset > + ) > +{ > + UINT64 ExtendOffset; > + > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUin= tX > + // > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03); > + > + if (PciIoDevice->IsPciExp) { > + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >=3D > PCI_EXP_MAX_CONFIG_OFFSET) { > + return EFI_UNSUPPORTED; > + } > + > + ExtendOffset =3D LShiftU64 (*Offset, 32); > + *Offset =3D EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevi= ce- > >DeviceNumber, PciIoDevice->FunctionNumber, 0); > + *Offset =3D (*Offset) | ExtendOffset; > + > + } else { > + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >=3D > PCI_MAX_CONFIG_OFFSET) { > + return EFI_UNSUPPORTED; > + } > + > + *Offset =3D EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice- > >DeviceNumber, PciIoDevice->FunctionNumber, *Offset); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Reads from the memory space of a PCI controller. Returns either when t= he > polling exit criteria is > + satisfied or after a defined duration. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory operation to= perform. > + @param Offset The offset within the selected BAR to st= art the > memory operation. > + @param Mask Mask used for the polling criteria. > + @param Value The comparison value used for the pollin= g exit > criteria. > + @param Delay The number of 100 ns units to poll. > + @param Result Pointer to the last value read from the = memory > location. > + > + @retval EFI_SUCCESS The last data returned from the access m= atched > the poll exit criteria. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of = this > PCI controller. > + @retval EFI_TIMEOUT Delay expired before a match occurred. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoPollMem ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINT64 Mask, > + IN UINT64 Value, > + IN UINT64 Delay, > + OUT UINT64 *Result > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, > Width, 1, &Offset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + if (Width > EfiPciIoWidthUint64) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Status =3D PciIoMemRead (This, Width, BarIndex, Offset, 1, Result= ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + if ((*Result & Mask) =3D=3D Value || Delay =3D=3D 0) { > + return EFI_SUCCESS; > + } > + do { > + // > + // Stall 10 us =3D 100 * 100ns > + // > + gBS->Stall (10); > + > + Status =3D PciIoMemRead (This, Width, BarIndex, Offset, 1, Resu= lt); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + if ((*Result & Mask) =3D=3D Value) { > + return EFI_SUCCESS; > + } > + if (Delay <=3D 100) { > + return EFI_TIMEOUT; > + } > + Delay -=3D 100; > + } while (TRUE); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->PollMem ( > + PciIoDevice->PciRootBridgeIo, > + (EFI_PCI_ROOT_BRIDGE_IO_PROTO= COL_WIDTH) > Width, > + Offset, > + Mask, > + Value, > + Delay, > + Result > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Reads from the memory space of a PCI controller. Returns either when t= he > polling exit criteria is > + satisfied or after a defined duration. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory operation to= perform. > + @param Offset The offset within the selected BAR to st= art the > memory operation. > + @param Mask Mask used for the polling criteria. > + @param Value The comparison value used for the pollin= g exit > criteria. > + @param Delay The number of 100 ns units to poll. > + @param Result Pointer to the last value read from the = memory > location. > + > + @retval EFI_SUCCESS The last data returned from the access m= atched > the poll exit criteria. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of = this > PCI controller. > + @retval EFI_TIMEOUT Delay expired before a match occurred. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoPollIo ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINT64 Mask, > + IN UINT64 Value, > + IN UINT64 Delay, > + OUT UINT64 *Result > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Width > EfiPciIoWidthUint64) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, = Width, > 1, &Offset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Status =3D PciIoIoRead (This, Width, BarIndex, Offset, 1, Result)= ; > + if (EFI_ERROR (Status)) { > + return Status; > + } > + if ((*Result & Mask) =3D=3D Value || Delay =3D=3D 0) { > + return EFI_SUCCESS; > + } > + do { > + // > + // Stall 10 us =3D 100 * 100ns > + // > + gBS->Stall (10); > + > + Status =3D PciIoIoRead (This, Width, BarIndex, Offset, 1, Resul= t); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + if ((*Result & Mask) =3D=3D Value) { > + return EFI_SUCCESS; > + } > + if (Delay <=3D 100) { > + return EFI_TIMEOUT; > + } > + Delay -=3D 100; > + } while (TRUE); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->PollIo ( > + PciIoDevice->PciRootBridgeIo, > + (EFI_PCI_ROOT_BRIDGE_IO_PROTO= COL_WIDTH) > Width, > + Offset, > + Mask, > + Value, > + Delay, > + Result > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoMemRead ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Buffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, > Width, Count, &Offset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Count *=3D (UINTN)(1 << (Width & 0x03)); > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03)); > + } > + } > + > + > + Status =3D PciIoDevice->PciRootBridgeIo->Mem.Read ( > + PciIoDevice->PciRootBridge= Io, > + (EFI_PCI_ROOT_BRIDGE_IO_PR= OTOCOL_WIDTH) > Width, > + Offset, > + Count, > + Buffer > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoMemWrite ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Buffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, > Width, Count, &Offset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Count *=3D (UINTN)(1 << (Width & 0x03)); > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03)); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->Mem.Write ( > + PciIoDevice->PciRootBridge= Io, > + (EFI_PCI_ROOT_BRIDGE_IO_PR= OTOCOL_WIDTH) > Width, > + Offset, > + Count, > + Buffer > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoIoRead ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Buffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, = Width, > Count, &Offset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Count *=3D (UINTN)(1 << (Width & 0x03)); > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03)); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->Io.Read ( > + PciIoDevice->PciRootBridge= Io, > + (EFI_PCI_ROOT_BRIDGE_IO_PR= OTOCOL_WIDTH) > Width, > + Offset, > + Count, > + Buffer > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoIoWrite ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Buffer =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, = Width, > Count, &Offset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Count *=3D (UINTN)(1 << (Width & 0x03)); > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03)); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->Io.Write ( > + PciIoDevice->PciRootBridge= Io, > + (EFI_PCI_ROOT_BRIDGE_IO_PR= OTOCOL_WIDTH) > Width, > + Offset, > + Count, > + Buffer > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Enable a PCI driver to access PCI controller registers in PCI configur= ation > space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory operat= ions. > + @param Offset The offset within the PCI configuration = space for > the PCI controller. > + @param Count The number of PCI configuration operatio= ns to > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI configuration header o= f the PCI controller. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoConfigRead ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT32 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + UINT64 Address; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + Address =3D Offset; > + Status =3D PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &A= ddress); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Count *=3D (UINTN)(1 << (Width & 0x03)); > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03)); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->Pci.Read ( > + PciIoDevice->PciRootBridg= eIo, > + (EFI_PCI_ROOT_BRIDGE_IO_P= ROTOCOL_WIDTH) > Width, > + Address, > + Count, > + Buffer > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Enable a PCI driver to access PCI controller registers in PCI configur= ation > space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory operat= ions. > + @param Offset The offset within the PCI configuration = space for > the PCI controller. > + @param Count The number of PCI configuration operatio= ns to > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI configuration header o= f the PCI controller. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoConfigWrite ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT32 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + UINT64 Address; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + Address =3D Offset; > + Status =3D PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &A= ddress); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((Offset & ((1 << (Width & 0x03)) - 1)) !=3D 0) { > + Count *=3D (UINTN)(1 << (Width & 0x03)); > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03)); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->Pci.Write ( > + PciIoDevice->PciRootBridge= Io, > + (EFI_PCI_ROOT_BRIDGE_IO_PR= OTOCOL_WIDTH) > Width, > + Address, > + Count, > + Buffer > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Enables a PCI driver to copy one region of PCI memory space to another > region of PCI > + memory space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory operat= ions. > + @param DestBarIndex The BAR index in the standard PCI > Configuration header to use as the > + base address for the memory operation to= perform. > + @param DestOffset The destination offset within the BAR sp= ecified > by DestBarIndex to > + start the memory writes for the copy ope= ration. > + @param SrcBarIndex The BAR index in the standard PCI Config= uration > header to use as the > + base address for the memory operation to= perform. > + @param SrcOffset The source offset within the BAR specifi= ed by > SrcBarIndex to start > + the memory reads for the copy operation. > + @param Count The number of memory operations to perfo= rm. > Bytes moved is Width > + size * Count, starting at DestOffset and= SrcOffset. > + > + @retval EFI_SUCCESS The data was copied from one memory regi= on > to another memory region. > + @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI > controller. > + @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI contr= oller. > + @retval EFI_UNSUPPORTED The address range specified by DestOffse= t, > Width, and Count > + is not valid for the PCI BAR specified b= y DestBarIndex. > + @retval EFI_UNSUPPORTED The address range specified by SrcOffset= , > Width, and Count is > + not valid for the PCI BAR specified by S= rcBarIndex. > + @retval EFI_INVALID_PARAMETER Width is invalid. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoCopyMem ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 DestBarIndex, > + IN UINT64 DestOffset, > + IN UINT8 SrcBarIndex, > + IN UINT64 SrcOffset, > + IN UINTN Count > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Width >=3D EfiPciIoWidthMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Width =3D=3D EfiPciIoWidthFifoUint8 || > + Width =3D=3D EfiPciIoWidthFifoUint16 || > + Width =3D=3D EfiPciIoWidthFifoUint32 || > + Width =3D=3D EfiPciIoWidthFifoUint64 || > + Width =3D=3D EfiPciIoWidthFillUint8 || > + Width =3D=3D EfiPciIoWidthFillUint16 || > + Width =3D=3D EfiPciIoWidthFillUint32 || > + Width =3D=3D EfiPciIoWidthFillUint64) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, > PciBarTypeMem, Width, Count, &DestOffset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + Status =3D PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeM= em, > Width, Count, &SrcOffset); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // If request is not aligned, then convert request to EfiPciIoWithXXXU= int8 > + // > + if (FeaturePcdGet (PcdUnalignedPciIoEnable)) { > + if ((SrcOffset & ((1 << (Width & 0x03)) - 1)) !=3D 0 || (DestOffset = & ((1 << > (Width & 0x03)) - 1)) !=3D 0) { > + Count *=3D (UINTN)(1 << (Width & 0x03)); > + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & (~0x03)); > + } > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->CopyMem ( > + PciIoDevice->PciRootBridgeIo, > + (EFI_PCI_ROOT_BRIDGE_IO_PROTOC= OL_WIDTH) > Width, > + DestOffset, > + SrcOffset, > + Count > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Provides the PCI controller-specific addresses needed to access system > memory. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Operation Indicates if the bus master is going to = read or > write to system memory. > + @param HostAddress The system memory address to map to the = PCI > controller. > + @param NumberOfBytes On input the number of bytes to map. On > output the number of bytes > + that were mapped. > + @param DeviceAddress The resulting map address for the bus ma= ster > PCI controller to use to > + access the hosts HostAddress. > + @param Mapping A resulting value to pass to Unmap(). > + > + @retval EFI_SUCCESS The range was mapped for the returned > NumberOfBytes. > + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a > common buffer. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_DEVICE_ERROR The system hardware could not map the > requested address. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoMap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, > + IN VOID *HostAddress, > + IN OUT UINTN *NumberOfBytes, > + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, > + OUT VOID **Mapping > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + UINT64 IoMmuAttribute; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION > RootBridgeIoOperation; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((UINT32)Operation >=3D EfiPciIoOperationMaximum) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (HostAddress =3D=3D NULL || NumberOfBytes =3D=3D NULL || DeviceAddr= ess =3D=3D > NULL || Mapping =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + RootBridgeIoOperation =3D > (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation; > + if ((PciIoDevice->Attributes & > EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) !=3D 0) { > + RootBridgeIoOperation =3D > (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation + > EfiPciOperationBusMasterRead64); > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->Map ( > + PciIoDevice->PciRootBridgeIo, > + RootBridgeIoOperation, > + HostAddress, > + NumberOfBytes, > + DeviceAddress, > + Mapping > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + if (mIoMmuProtocol !=3D NULL) { > + if (!EFI_ERROR (Status)) { > + switch (Operation) { > + case EfiPciIoOperationBusMasterRead: > + IoMmuAttribute =3D EDKII_IOMMU_ACCESS_READ; > + break; > + case EfiPciIoOperationBusMasterWrite: > + IoMmuAttribute =3D EDKII_IOMMU_ACCESS_WRITE; > + break; > + case EfiPciIoOperationBusMasterCommonBuffer: > + IoMmuAttribute =3D EDKII_IOMMU_ACCESS_READ | > EDKII_IOMMU_ACCESS_WRITE; > + break; > + default: > + ASSERT(FALSE); > + return EFI_INVALID_PARAMETER; > + } > + mIoMmuProtocol->SetAttribute ( > + mIoMmuProtocol, > + PciIoDevice->Handle, > + *Mapping, > + IoMmuAttribute > + ); > + } > + } > + > + return Status; > +} > + > +/** > + Completes the Map() operation and releases any corresponding > resources. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Mapping The mapping value returned from Map(). > + > + @retval EFI_SUCCESS The range was unmapped. > + @retval EFI_DEVICE_ERROR The data was not committed to the target > system memory. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoUnmap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN VOID *Mapping > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if (mIoMmuProtocol !=3D NULL) { > + mIoMmuProtocol->SetAttribute ( > + mIoMmuProtocol, > + PciIoDevice->Handle, > + Mapping, > + 0 > + ); > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->Unmap ( > + PciIoDevice->PciRootBridgeIo, > + Mapping > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Allocates pages that are suitable for an > EfiPciIoOperationBusMasterCommonBuffer > + or EfiPciOperationBusMasterCommonBuffer64 mapping. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Type This parameter is not used and must be i= gnored. > + @param MemoryType The type of memory to allocate, > EfiBootServicesData or > + EfiRuntimeServicesData. > + @param Pages The number of pages to allocate. > + @param HostAddress A pointer to store the base system memor= y > address of the > + allocated range. > + @param Attributes The requested bit mask of attributes for= the > allocated range. > + > + @retval EFI_SUCCESS The requested memory pages were allocate= d. > + @retval EFI_UNSUPPORTED Attributes is unsupported. The only lega= l > attribute bits are > + MEMORY_WRITE_COMBINE, MEMORY_CACHED and > DUAL_ADDRESS_CYCLE. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_OUT_OF_RESOURCES The memory pages could not be > allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoAllocateBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN Pages, > + OUT VOID **HostAddress, > + IN UINT64 Attributes > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + if ((Attributes & > + (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | > EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) !=3D 0){ > + return EFI_UNSUPPORTED; > + } > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if ((PciIoDevice->Attributes & > EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) !=3D 0) { > + Attributes |=3D EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE; > + } > + > + Status =3D PciIoDevice->PciRootBridgeIo->AllocateBuffer ( > + PciIoDevice->PciRootBridgeIo, > + Type, > + MemoryType, > + Pages, > + HostAddress, > + Attributes > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Frees memory that was allocated with AllocateBuffer(). > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Pages The number of pages to free. > + @param HostAddress The base system memory address of the > allocated range. > + > + @retval EFI_SUCCESS The requested memory pages were freed. > + @retval EFI_INVALID_PARAMETER The memory range specified by > HostAddress and Pages > + was not allocated with AllocateBuffer(). > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoFreeBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN UINTN Pages, > + IN VOID *HostAddress > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + Status =3D PciIoDevice->PciRootBridgeIo->FreeBuffer ( > + PciIoDevice->PciRootBridgeIo, > + Pages, > + HostAddress > + ); > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Flushes all PCI posted write transactions from a PCI host bridge to sy= stem > memory. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + > + @retval EFI_SUCCESS The PCI posted write transactions were f= lushed > from the PCI host > + bridge to system memory. > + @retval EFI_DEVICE_ERROR The PCI posted write transactions were n= ot > flushed from the PCI > + host bridge due to a hardware error. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoFlush ( > + IN EFI_PCI_IO_PROTOCOL *This > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + Status =3D PciIoDevice->PciRootBridgeIo->Flush ( > + PciIoDevice->PciRootBridgeIo > + ); > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Retrieves this PCI controller's current PCI bus number, device number,= and > function number. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param SegmentNumber The PCI controller's current PCI segment > number. > + @param BusNumber The PCI controller's current PCI bus num= ber. > + @param DeviceNumber The PCI controller's current PCI device > number. > + @param FunctionNumber The PCI controller's current PCI functio= n > number. > + > + @retval EFI_SUCCESS The PCI controller location was returned= . > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoGetLocation ( > + IN EFI_PCI_IO_PROTOCOL *This, > + OUT UINTN *Segment, > + OUT UINTN *Bus, > + OUT UINTN *Device, > + OUT UINTN *Function > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if (Segment =3D=3D NULL || Bus =3D=3D NULL || Device =3D=3D NULL || Fu= nction =3D=3D > NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + *Segment =3D PciIoDevice->PciRootBridgeIo->SegmentNumber; > + *Bus =3D PciIoDevice->BusNumber; > + *Device =3D PciIoDevice->DeviceNumber; > + *Function =3D PciIoDevice->FunctionNumber; > + > + return EFI_SUCCESS; > +} > + > +/** > + Check BAR type for PCI resource. > + > + @param PciIoDevice PCI device instance. > + @param BarIndex The BAR index of the standard PCI Configuration > header to use as the > + base address for the memory or I/O operation to p= erform. > + @param BarType Memory or I/O. > + > + @retval TRUE Pci device's bar type is same with input BarType. > + @retval TRUE Pci device's bar type is not same with input BarT= ype. > + > +**/ > +BOOLEAN > +CheckBarType ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 BarIndex, > + IN PCI_BAR_TYPE BarType > + ) > +{ > + switch (BarType) { > + > + case PciBarTypeMem: > + > + if (PciIoDevice->PciBar[BarIndex].BarType !=3D PciBarTypeMem32 && > + PciIoDevice->PciBar[BarIndex].BarType !=3D PciBarTypePMem32 && > + PciIoDevice->PciBar[BarIndex].BarType !=3D PciBarTypePMem64 && > + PciIoDevice->PciBar[BarIndex].BarType !=3D PciBarTypeMem64 ) = { > + return FALSE; > + } > + > + return TRUE; > + > + case PciBarTypeIo: > + if (PciIoDevice->PciBar[BarIndex].BarType !=3D PciBarTypeIo32 && > + PciIoDevice->PciBar[BarIndex].BarType !=3D PciBarTypeIo16){ > + return FALSE; > + } > + > + return TRUE; > + > + default: > + break; > + } > + > + return FALSE; > +} > + > +/** > + Set/Disable new attributes to a Root Bridge. > + > + @param PciIoDevice Pci device instance. > + @param Attributes New attribute want to be set. > + @param Operation Set or Disable. > + > + @retval EFI_UNSUPPORTED If root bridge does not support change > attribute. > + @retval EFI_SUCCESS Successfully set new attributes. > + > +**/ > +EFI_STATUS > +ModifyRootBridgeAttributes ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT64 Attributes, > + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation > + ) > +{ > + UINT64 PciRootBridgeSupports; > + UINT64 PciRootBridgeAttributes; > + UINT64 NewPciRootBridgeAttributes; > + EFI_STATUS Status; > + > + // > + // Get the current attributes of this PCI device's PCI Root Bridge > + // > + Status =3D PciIoDevice->PciRootBridgeIo->GetAttributes ( > + PciIoDevice->PciRootBridgeIo, > + &PciRootBridgeSupports, > + &PciRootBridgeAttributes > + ); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Mask off attributes not supported by PCI root bridge. > + // > + Attributes &=3D ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE | > + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM | > + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE); > + > + // > + // Record the new attribute of the Root Bridge > + // > + if (Operation =3D=3D EfiPciIoAttributeOperationEnable) { > + NewPciRootBridgeAttributes =3D PciRootBridgeAttributes | Attributes; > + } else { > + NewPciRootBridgeAttributes =3D PciRootBridgeAttributes & (~Attribute= s); > + } > + > + // > + // Call the PCI Root Bridge to attempt to modify the attributes > + // > + if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) !=3D 0) { > + > + Status =3D PciIoDevice->PciRootBridgeIo->SetAttributes ( > + PciIoDevice->PciRootBridgeIo= , > + NewPciRootBridgeAttributes, > + NULL, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + // > + // The PCI Root Bridge could not modify the attributes, so return = the > error. > + // > + return EFI_UNSUPPORTED; > + } > + } > + > + // > + // Also update the attributes for this Root Bridge structure > + // > + PciIoDevice->Attributes =3D NewPciRootBridgeAttributes; > + > + return EFI_SUCCESS; > +} > + > +/** > + Check whether this device can be enable/disable to snoop. > + > + @param PciIoDevice Pci device instance. > + @param Operation Enable/Disable. > + > + @retval EFI_UNSUPPORTED Pci device is not GFX device or not support > snoop. > + @retval EFI_SUCCESS Snoop can be supported. > + > +**/ > +EFI_STATUS > +SupportPaletteSnoopAttributes ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation > + ) > +{ > + PCI_IO_DEVICE *Temp; > + UINT16 VGACommand; > + > + // > + // Snoop attribute can be only modified by GFX > + // > + if (!IS_PCI_GFX (&PciIoDevice->Pci)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Get the boot VGA on the same Host Bridge > + // > + Temp =3D LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo- > >ParentHandle); > + > + if (Temp =3D=3D NULL) { > + // > + // If there is no VGA device on the segment, set > + // this graphics card to decode the palette range > + // > + return EFI_SUCCESS; > + } > + > + // > + // Check these two agents are on the same path > + // > + if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) { > + // > + // they are not on the same path, so snoop can be enabled or disable= d > + // > + return EFI_SUCCESS; > + } > + // > + // Check if they are on the same bus > + // > + if (Temp->Parent =3D=3D PciIoDevice->Parent) { > + > + PCI_READ_COMMAND_REGISTER (Temp, &VGACommand); > + > + // > + // If they are on the same bus, either one can > + // be set to snoop, the other set to decode > + // > + if ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) !=3D 0) { > + // > + // VGA has set to snoop, so GFX can be only set to disable snoop > + // > + if (Operation =3D=3D EfiPciIoAttributeOperationEnable) { > + return EFI_UNSUPPORTED; > + } > + } else { > + // > + // VGA has disabled to snoop, so GFX can be only enabled > + // > + if (Operation =3D=3D EfiPciIoAttributeOperationDisable) { > + return EFI_UNSUPPORTED; > + } > + } > + > + return EFI_SUCCESS; > + } > + > + // > + // If they are on the same path but on the different bus > + // The first agent is set to snoop, the second one set to > + // decode > + // > + > + if (Temp->BusNumber < PciIoDevice->BusNumber) { > + // > + // GFX should be set to decode > + // > + if (Operation =3D=3D EfiPciIoAttributeOperationDisable) { > + PCI_ENABLE_COMMAND_REGISTER (Temp, > EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); > + Temp->Attributes |=3D EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; > + } else { > + return EFI_UNSUPPORTED; > + } > + > + } else { > + // > + // GFX should be set to snoop > + // > + if (Operation =3D=3D EfiPciIoAttributeOperationEnable) { > + PCI_DISABLE_COMMAND_REGISTER (Temp, > EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); > + Temp->Attributes &=3D > (~(UINT64)EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); > + } else { > + return EFI_UNSUPPORTED; > + } > + > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Performs an operation on the attributes that this PCI controller suppo= rts. > The operations include > + getting the set of supported attributes, retrieving the current attrib= utes, > setting the current > + attributes, enabling attributes, and disabling attributes. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Operation The operation to perform on the attribut= es for > this PCI controller. > + @param Attributes The mask of attributes that are used for= Set, > Enable, and Disable > + operations. > + @param Result A pointer to the result mask of attribut= es that are > returned for the Get > + and Supported operations. > + > + @retval EFI_SUCCESS The operation on the PCI controller's at= tributes > was completed. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_UNSUPPORTED one or more of the bits set in > + Attributes are not supported by this PCI= controller or one of > + its parent bridges when Operation is Set= , Enable or Disable. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoAttributes ( > + IN EFI_PCI_IO_PROTOCOL * This, > + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, > + IN UINT64 Attributes, > + OUT UINT64 *Result OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + > + PCI_IO_DEVICE *PciIoDevice; > + PCI_IO_DEVICE *UpStreamBridge; > + PCI_IO_DEVICE *Temp; > + > + UINT64 Supports; > + UINT64 UpStreamAttributes; > + UINT16 BridgeControl; > + UINT16 Command; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + switch (Operation) { > + case EfiPciIoAttributeOperationGet: > + if (Result =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + *Result =3D PciIoDevice->Attributes; > + return EFI_SUCCESS; > + > + case EfiPciIoAttributeOperationSupported: > + if (Result =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + *Result =3D PciIoDevice->Supports; > + return EFI_SUCCESS; > + > + case EfiPciIoAttributeOperationSet: > + Status =3D PciIoDevice->PciIo.Attributes ( > + &(PciIoDevice->PciIo), > + EfiPciIoAttributeOperationEnable, > + Attributes, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + Status =3D PciIoDevice->PciIo.Attributes ( > + &(PciIoDevice->PciIo), > + EfiPciIoAttributeOperationDisable, > + (~Attributes) & (PciIoDevice->Supports= ), > + NULL > + ); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + return EFI_SUCCESS; > + > + case EfiPciIoAttributeOperationEnable: > + case EfiPciIoAttributeOperationDisable: > + break; > + > + default: > + return EFI_INVALID_PARAMETER; > + } > + // > + // Just a trick for ENABLE attribute > + // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the > internal usage. > + // So, this logic doesn't conform to UEFI spec, which should be remove= d. > + // But this trick logic is still kept for some binary drivers that dep= end on it. > + // > + if ((Attributes & EFI_PCI_DEVICE_ENABLE) =3D=3D EFI_PCI_DEVICE_ENABLE)= { > + Attributes &=3D (PciIoDevice->Supports); > + > + // > + // Raise the EFI_P_PC_ENABLE Status code > + // > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_PROGRESS_CODE, > + EFI_IO_BUS_PCI | EFI_P_PC_ENABLE, > + PciIoDevice->DevicePath > + ); > + } > + > + // > + // Check VGA and VGA16, they can not be set at the same time > + // > + if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | > EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) !=3D 0) { > + if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | > EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) !=3D 0) { > + return EFI_UNSUPPORTED; > + } > + } > + > + // > + // If no attributes can be supported, then return. > + // Otherwise, set the attributes that it can support. > + // > + Supports =3D (PciIoDevice->Supports) & Attributes; > + if (Supports !=3D Attributes) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // For Root Bridge, just call RootBridgeIo to set attributes; > + // > + if (PciIoDevice->Parent =3D=3D NULL) { > + Status =3D ModifyRootBridgeAttributes (PciIoDevice, Attributes, > Operation); > + return Status; > + } > + > + Command =3D 0; > + BridgeControl =3D 0; > + > + // > + // For PPB & P2C, set relevant attribute bits > + // > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE > (&PciIoDevice->Pci)) { > + > + if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | > EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) !=3D 0) { > + BridgeControl |=3D EFI_PCI_BRIDGE_CONTROL_VGA; > + } > + > + if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) !=3D 0) { > + BridgeControl |=3D EFI_PCI_BRIDGE_CONTROL_ISA; > + } > + > + if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | > EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) !=3D 0) { > + Command |=3D EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; > + } > + > + if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | > EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) !=3D 0) { > + BridgeControl |=3D EFI_PCI_BRIDGE_CONTROL_VGA_16; > + } > + > + } else { > + // > + // Do with the attributes on VGA > + // Only for VGA's legacy resource, we just can enable once. > + // > + if ((Attributes & > + (EFI_PCI_IO_ATTRIBUTE_VGA_IO | > + EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | > + EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) !=3D 0) { > + // > + // Check if a VGA has been enabled before enabling a new one > + // > + if (Operation =3D=3D EfiPciIoAttributeOperationEnable) { > + // > + // Check if there have been an active VGA device on the same Hos= t > Bridge > + // > + Temp =3D LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridge= Io- > >ParentHandle); > + if (Temp !=3D NULL && Temp !=3D PciIoDevice) { > + // > + // An active VGA has been detected, so can not enable another > + // > + return EFI_UNSUPPORTED; > + } > + } > + } > + > + // > + // Do with the attributes on GFX > + // > + if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | > EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) !=3D 0) { > + > + if (Operation =3D=3D EfiPciIoAttributeOperationEnable) { > + // > + // Check if snoop can be enabled in current configuration > + // > + Status =3D SupportPaletteSnoopAttributes (PciIoDevice, Operation= ); > + > + if (EFI_ERROR (Status)) { > + > + // > + // Enable operation is forbidden, so mask the bit in attribute= s > + // so as to keep consistent with the actual Status > + // > + // Attributes &=3D (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO); > + // > + // > + // > + return EFI_UNSUPPORTED; > + > + } > + } > + > + // > + // It can be supported, so get ready to set the bit > + // > + Command |=3D EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; > + } > + } > + > + if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) !=3D 0) { > + Command |=3D EFI_PCI_COMMAND_IO_SPACE; > + } > + > + if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) !=3D 0) { > + Command |=3D EFI_PCI_COMMAND_MEMORY_SPACE; > + } > + > + if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) !=3D 0) { > + Command |=3D EFI_PCI_COMMAND_BUS_MASTER; > + } > + // > + // The upstream bridge should be also set to relevant attribute > + // expect for IO, Mem and BusMaster > + // > + UpStreamAttributes =3D Attributes & > + (~(EFI_PCI_IO_ATTRIBUTE_IO | > + EFI_PCI_IO_ATTRIBUTE_MEMORY | > + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER > + ) > + ); > + UpStreamBridge =3D PciIoDevice->Parent; > + > + if (Operation =3D=3D EfiPciIoAttributeOperationEnable) { > + // > + // Enable relevant attributes to command register and bridge control > register > + // > + Status =3D PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command); > + if (BridgeControl !=3D 0) { > + Status =3D PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, > BridgeControl); > + } > + > + PciIoDevice->Attributes |=3D Attributes; > + > + // > + // Enable attributes of the upstream bridge > + // > + Status =3D UpStreamBridge->PciIo.Attributes ( > + &(UpStreamBridge->PciIo), > + EfiPciIoAttributeOperationEnable, > + UpStreamAttributes, > + NULL > + ); > + } else { > + > + // > + // Disable relevant attributes to command register and bridge contro= l > register > + // > + Status =3D PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command); > + if (BridgeControl !=3D 0) { > + Status =3D PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, > BridgeControl); > + } > + > + PciIoDevice->Attributes &=3D (~Attributes); > + Status =3D EFI_SUCCESS; > + > + } > + > + if (EFI_ERROR (Status)) { > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_ERROR_CODE | EFI_ERROR_MINOR, > + EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR, > + PciIoDevice->DevicePath > + ); > + } > + > + return Status; > +} > + > +/** > + Retrieve the AddrTranslationOffset from RootBridgeIo for the > + specified range. > + > + @param RootBridgeIo Root Bridge IO instance. > + @param AddrRangeMin The base address of the MMIO. > + @param AddrLen The length of the MMIO. > + > + @retval The AddrTranslationOffset from RootBridgeIo for the > + specified range, or (UINT64) -1 if the range is not > + found in RootBridgeIo. > +**/ > +UINT64 > +GetMmioAddressTranslationOffset ( > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo, > + UINT64 AddrRangeMin, > + UINT64 AddrLen > + ) > +{ > + EFI_STATUS Status; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration; > + > + Status =3D RootBridgeIo->Configuration ( > + RootBridgeIo, > + (VOID **) &Configuration > + ); > + if (EFI_ERROR (Status)) { > + return (UINT64) -1; > + } > + > + // According to UEFI 2.7, > EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration() > + // returns host address instead of device address, while > AddrTranslationOffset > + // is not zero, and device address =3D host address + AddrTranslationO= ffset, > so > + // we convert host address to device address for range compare. > + while (Configuration->Desc =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR) { > + if ((Configuration->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_MEM) && > + (Configuration->AddrRangeMin + Configuration- > >AddrTranslationOffset <=3D AddrRangeMin) && > + (Configuration->AddrRangeMin + Configuration->AddrLen + > Configuration->AddrTranslationOffset >=3D AddrRangeMin + AddrLen) > + ) { > + return Configuration->AddrTranslationOffset; > + } > + Configuration++; > + } > + > + // > + // The resource occupied by BAR should be in the range reported by > RootBridge. > + // > + ASSERT (FALSE); > + return (UINT64) -1; > +} > + > +/** > + Gets the attributes that this PCI controller supports setting on a BAR= using > + SetBarAttributes(), and retrieves the list of resource descriptors for= a BAR. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for resource range. The leg= al range for this > field is 0..5. > + @param Supports A pointer to the mask of attributes that= this PCI > controller supports > + setting for this BAR with SetBarAttribut= es(). > + @param Resources A pointer to the resource descriptors th= at > describe the current > + configuration of this BAR of the PCI con= troller. > + > + @retval EFI_SUCCESS If Supports is not NULL, then the attrib= utes that > the PCI > + controller supports are returned in Supp= orts. If Resources > + is not NULL, then the resource descripto= rs that the PCI > + controller is currently using are return= ed in Resources. > + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_OUT_OF_RESOURCES There are not enough resources > available to allocate > + Resources. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoGetBarAttributes ( > + IN EFI_PCI_IO_PROTOCOL * This, > + IN UINT8 BarIndex, > + OUT UINT64 *Supports, OPTIONAL > + OUT VOID **Resources OPTIONAL > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor; > + EFI_ACPI_END_TAG_DESCRIPTOR *End; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + if (Supports =3D=3D NULL && Resources =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((BarIndex >=3D PCI_MAX_BAR) || (PciIoDevice- > >PciBar[BarIndex].BarType =3D=3D PciBarTypeUnknown)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // This driver does not support modifications to the WRITE_COMBINE or > + // CACHED attributes for BAR ranges. > + // > + if (Supports !=3D NULL) { > + *Supports =3D PciIoDevice->Supports & > EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & > EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; > + } > + > + if (Resources !=3D NULL) { > + Descriptor =3D AllocateZeroPool (sizeof > (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof > (EFI_ACPI_END_TAG_DESCRIPTOR)); > + if (Descriptor =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + *Resources =3D Descriptor; > + > + Descriptor->Desc =3D ACPI_ADDRESS_SPACE_DESCRIPTOR; > + Descriptor->Len =3D (UINT16) (sizeof > (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3); > + Descriptor->AddrRangeMin =3D PciIoDevice- > >PciBar[BarIndex].BaseAddress; > + Descriptor->AddrLen =3D PciIoDevice->PciBar[BarIndex].Length; > + Descriptor->AddrRangeMax =3D PciIoDevice->PciBar[BarIndex].Alignment= ; > + > + switch (PciIoDevice->PciBar[BarIndex].BarType) { > + case PciBarTypeIo16: > + case PciBarTypeIo32: > + // > + // Io > + // > + Descriptor->ResType =3D ACPI_ADDRESS_SPACE_TYPE_IO; > + break; > + > + case PciBarTypePMem32: > + // > + // prefetchable > + // > + Descriptor->SpecificFlag =3D > EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABL > E; > + // > + // Fall through > + // > + case PciBarTypeMem32: > + // > + // Mem > + // > + Descriptor->ResType =3D ACPI_ADDRESS_SPACE_TYPE_MEM; > + // > + // 32 bit > + // > + Descriptor->AddrSpaceGranularity =3D 32; > + break; > + > + case PciBarTypePMem64: > + // > + // prefetchable > + // > + Descriptor->SpecificFlag =3D > EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABL > E; > + // > + // Fall through > + // > + case PciBarTypeMem64: > + // > + // Mem > + // > + Descriptor->ResType =3D ACPI_ADDRESS_SPACE_TYPE_MEM; > + // > + // 64 bit > + // > + Descriptor->AddrSpaceGranularity =3D 64; > + break; > + > + default: > + break; > + } > + > + // > + // put the checksum > + // > + End =3D (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1); > + End->Desc =3D ACPI_END_TAG_DESCRIPTOR; > + End->Checksum =3D 0; > + > + // > + // Get the Address Translation Offset > + // > + if (Descriptor->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_MEM) { > + Descriptor->AddrTranslationOffset =3D GetMmioAddressTranslationOff= set > ( > + PciIoDevice->PciRootBridgeIo= , > + Descriptor->AddrRangeMin, > + Descriptor->AddrLen > + ); > + if (Descriptor->AddrTranslationOffset =3D=3D (UINT64) -1) { > + FreePool (Descriptor); > + return EFI_UNSUPPORTED; > + } > + } > + > + // According to UEFI spec 2.7, we need return host address for > + // PciIo->GetBarAttributes, and host address =3D device address - > translation. > + Descriptor->AddrRangeMin -=3D Descriptor->AddrTranslationOffset; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Sets the attributes for a range of a BAR on a PCI controller. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Attributes The mask of attributes to set for the re= source > range specified by > + BarIndex, Offset, and Length. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for resource range. The leg= al range for this > field is 0..5. > + @param Offset A pointer to the BAR relative base addre= ss of the > resource range to be > + modified by the attributes specified by = Attributes. > + @param Length A pointer to the length of the resource = range to > be modified by the > + attributes specified by Attributes. > + > + @retval EFI_SUCCESS The set of attributes specified by Attri= butes for > the resource > + range specified by BarIndex, Offset, and= Length were > + set on the PCI controller, and the actua= l resource range is > returned > + in Offset and Length. > + @retval EFI_INVALID_PARAMETER Offset or Length is NULL. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set > the attributes on the > + resource range specified by BarIndex, Of= fset, and > + Length. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoSetBarAttributes ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN UINT64 Attributes, > + IN UINT8 BarIndex, > + IN OUT UINT64 *Offset, > + IN OUT UINT64 *Length > + ) > +{ > + EFI_STATUS Status; > + PCI_IO_DEVICE *PciIoDevice; > + UINT64 NonRelativeOffset; > + UINT64 Supports; > + > + PciIoDevice =3D PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); > + > + // > + // Make sure Offset and Length are not NULL > + // > + if (Offset =3D=3D NULL || Length =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (PciIoDevice->PciBar[BarIndex].BarType =3D=3D PciBarTypeUnknown) { > + return EFI_UNSUPPORTED; > + } > + // > + // This driver does not support setting the WRITE_COMBINE or the > CACHED attributes. > + // If Attributes is not 0, then return EFI_UNSUPPORTED. > + // > + Supports =3D PciIoDevice->Supports & > EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & > EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; > + > + if (Attributes !=3D (Attributes & Supports)) { > + return EFI_UNSUPPORTED; > + } > + // > + // Attributes must be supported. Make sure the BAR range described by > BarIndex, Offset, and > + // Length are valid for this PCI device. > + // > + NonRelativeOffset =3D *Offset; > + Status =3D PciIoVerifyBarAccess ( > + PciIoDevice, > + BarIndex, > + PciBarTypeMem, > + EfiPciIoWidthUint8, > + (UINT32) *Length, > + &NonRelativeOffset > + ); > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Test whether two Pci devices has same parent bridge. > + > + @param PciDevice1 The first pci device for testing. > + @param PciDevice2 The second pci device for testing. > + > + @retval TRUE Two Pci device has the same parent bridge. > + @retval FALSE Two Pci device has not the same parent bridge. > + > +**/ > +BOOLEAN > +PciDevicesOnTheSamePath ( > + IN PCI_IO_DEVICE *PciDevice1, > + IN PCI_IO_DEVICE *PciDevice2 > + ) > +{ > + BOOLEAN Existed1; > + BOOLEAN Existed2; > + > + if (PciDevice1->Parent =3D=3D PciDevice2->Parent) { > + return TRUE; > + } > + > + Existed1 =3D PciDeviceExisted (PciDevice1->Parent, PciDevice2); > + Existed2 =3D PciDeviceExisted (PciDevice2->Parent, PciDevice1); > + > + return (BOOLEAN) (Existed1 || Existed2); > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciIo.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciIo.h > new file mode 100644 > index 0000000000..c00516ee6a > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciIo.h > @@ -0,0 +1,660 @@ > +/** @file > + EFI PCI IO protocol functions declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_IO_PROTOCOL_H_ > +#define _EFI_PCI_IO_PROTOCOL_H_ > + > +/** > + Initializes a PCI I/O Instance. > + > + @param PciIoDevice Pci device instance. > + > +**/ > +VOID > +InitializePciIoInstance ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Verifies access to a PCI Base Address Register (BAR). > + > + @param PciIoDevice Pci device instance. > + @param BarIndex The BAR index of the standard PCI Configuration > header to use as the > + base address for the memory or I/O operation to pe= rform. > + @param Type Operation type could be memory or I/O. > + @param Width Signifies the width of the memory or I/O operation= s. > + @param Count The number of memory or I/O operations to perform. > + @param Offset The offset within the PCI configuration space for = the PCI > controller. > + > + @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type. > + @retval EFI_SUCCESS Successfully verified. > + > +**/ > +EFI_STATUS > +PciIoVerifyBarAccess ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 BarIndex, > + IN PCI_BAR_TYPE Type, > + IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN IN UINTN Count, > + IN UINT64 *Offset > + ); > + > +/** > + Verifies access to a PCI Configuration Header. > + > + @param PciIoDevice Pci device instance. > + @param Width Signifies the width of the memory or I/O operation= s. > + @param Count The number of memory or I/O operations to perform. > + @param Offset The offset within the PCI configuration space for = the PCI > controller. > + > + @retval EFI_INVALID_PARAMETER Invalid Width > + @retval EFI_UNSUPPORTED Offset overflowed. > + @retval EFI_SUCCESS Successfully verified. > + > +**/ > +EFI_STATUS > +PciIoVerifyConfigAccess ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINTN Count, > + IN UINT64 *Offset > + ); > + > +/** > + Reads from the memory space of a PCI controller. Returns either when t= he > polling exit criteria is > + satisfied or after a defined duration. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory operation to= perform. > + @param Offset The offset within the selected BAR to st= art the > memory operation. > + @param Mask Mask used for the polling criteria. > + @param Value The comparison value used for the pollin= g exit > criteria. > + @param Delay The number of 100 ns units to poll. > + @param Result Pointer to the last value read from the = memory > location. > + > + @retval EFI_SUCCESS The last data returned from the access m= atched > the poll exit criteria. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of = this > PCI controller. > + @retval EFI_TIMEOUT Delay expired before a match occurred. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoPollMem ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINT64 Mask, > + IN UINT64 Value, > + IN UINT64 Delay, > + OUT UINT64 *Result > + ); > + > +/** > + Reads from the memory space of a PCI controller. Returns either when t= he > polling exit criteria is > + satisfied or after a defined duration. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory operation to= perform. > + @param Offset The offset within the selected BAR to st= art the > memory operation. > + @param Mask Mask used for the polling criteria. > + @param Value The comparison value used for the pollin= g exit > criteria. > + @param Delay The number of 100 ns units to poll. > + @param Result Pointer to the last value read from the = memory > location. > + > + @retval EFI_SUCCESS The last data returned from the access m= atched > the poll exit criteria. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of = this > PCI controller. > + @retval EFI_TIMEOUT Delay expired before a match occurred. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoPollIo ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINT64 Mask, > + IN UINT64 Value, > + IN UINT64 Delay, > + OUT UINT64 *Result > + ); > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoMemRead ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ); > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoMemWrite ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ); > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoIoRead ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ); > + > +/** > + Enable a PCI driver to access PCI controller registers in the PCI memo= ry or > I/O space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory or I/O > operations. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for the memory or I/O opera= tion to perform. > + @param Offset The offset within the selected BAR to st= art the > memory or I/O operation. > + @param Count The number of memory or I/O operations t= o > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI BAR specified by BarIn= dex. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoIoWrite ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 BarIndex, > + IN UINT64 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ); > + > +/** > + Enable a PCI driver to access PCI controller registers in PCI configur= ation > space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory operat= ions. > + @param Offset The offset within the PCI configuration = space for > the PCI controller. > + @param Count The number of PCI configuration operatio= ns to > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI configuration header o= f the PCI controller. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoConfigRead ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT32 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ); > + > +/** > + Enable a PCI driver to access PCI controller registers in PCI configur= ation > space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory operat= ions. > + @param Offset The offset within the PCI configuration = space for > the PCI controller. > + @param Count The number of PCI configuration operatio= ns to > perform. > + @param Buffer For read operations, the destination buf= fer to > store the results. For write > + operations, the source buffer to write d= ata from. > + > + > + @retval EFI_SUCCESS The data was read from or written to the= PCI > controller. > + @retval EFI_UNSUPPORTED The address range specified by Offset, > Width, and Count is not > + valid for the PCI configuration header o= f the PCI controller. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoConfigWrite ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT32 Offset, > + IN UINTN Count, > + IN OUT VOID *Buffer > + ); > + > +/** > + Enables a PCI driver to copy one region of PCI memory space to another > region of PCI > + memory space. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Width Signifies the width of the memory operat= ions. > + @param DestBarIndex The BAR index in the standard PCI > Configuration header to use as the > + base address for the memory operation to= perform. > + @param DestOffset The destination offset within the BAR sp= ecified > by DestBarIndex to > + start the memory writes for the copy ope= ration. > + @param SrcBarIndex The BAR index in the standard PCI Config= uration > header to use as the > + base address for the memory operation to= perform. > + @param SrcOffset The source offset within the BAR specifi= ed by > SrcBarIndex to start > + the memory reads for the copy operation. > + @param Count The number of memory operations to perfo= rm. > Bytes moved is Width > + size * Count, starting at DestOffset and= SrcOffset. > + > + @retval EFI_SUCCESS The data was copied from one memory regi= on > to another memory region. > + @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI > controller. > + @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI contr= oller. > + @retval EFI_UNSUPPORTED The address range specified by DestOffse= t, > Width, and Count > + is not valid for the PCI BAR specified b= y DestBarIndex. > + @retval EFI_UNSUPPORTED The address range specified by SrcOffset= , > Width, and Count is > + not valid for the PCI BAR specified by S= rcBarIndex. > + @retval EFI_INVALID_PARAMETER Width is invalid. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoCopyMem ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, > + IN UINT8 DestBarIndex, > + IN UINT64 DestOffset, > + IN UINT8 SrcBarIndex, > + IN UINT64 SrcOffset, > + IN UINTN Count > + ); > + > +/** > + Provides the PCI controller-specific addresses needed to access system > memory. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Operation Indicates if the bus master is going to = read or > write to system memory. > + @param HostAddress The system memory address to map to the = PCI > controller. > + @param NumberOfBytes On input the number of bytes to map. On > output the number of bytes > + that were mapped. > + @param DeviceAddress The resulting map address for the bus ma= ster > PCI controller to use to > + access the hosts HostAddress. > + @param Mapping A resulting value to pass to Unmap(). > + > + @retval EFI_SUCCESS The range was mapped for the returned > NumberOfBytes. > + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a > common buffer. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_OUT_OF_RESOURCES The request could not be completed > due to a lack of resources. > + @retval EFI_DEVICE_ERROR The system hardware could not map the > requested address. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoMap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, > + IN VOID *HostAddress, > + IN OUT UINTN *NumberOfBytes, > + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, > + OUT VOID **Mapping > + ); > + > +/** > + Completes the Map() operation and releases any corresponding > resources. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Mapping The mapping value returned from Map(). > + > + @retval EFI_SUCCESS The range was unmapped. > + @retval EFI_DEVICE_ERROR The data was not committed to the target > system memory. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoUnmap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN VOID *Mapping > + ); > + > +/** > + Allocates pages that are suitable for an > EfiPciIoOperationBusMasterCommonBuffer > + or EfiPciOperationBusMasterCommonBuffer64 mapping. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Type This parameter is not used and must be i= gnored. > + @param MemoryType The type of memory to allocate, > EfiBootServicesData or > + EfiRuntimeServicesData. > + @param Pages The number of pages to allocate. > + @param HostAddress A pointer to store the base system memor= y > address of the > + allocated range. > + @param Attributes The requested bit mask of attributes for= the > allocated range. > + > + @retval EFI_SUCCESS The requested memory pages were allocate= d. > + @retval EFI_UNSUPPORTED Attributes is unsupported. The only lega= l > attribute bits are > + MEMORY_WRITE_COMBINE, MEMORY_CACHED and > DUAL_ADDRESS_CYCLE. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_OUT_OF_RESOURCES The memory pages could not be > allocated. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoAllocateBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN Pages, > + OUT VOID **HostAddress, > + IN UINT64 Attributes > + ); > + > +/** > + Frees memory that was allocated with AllocateBuffer(). > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Pages The number of pages to free. > + @param HostAddress The base system memory address of the > allocated range. > + > + @retval EFI_SUCCESS The requested memory pages were freed. > + @retval EFI_INVALID_PARAMETER The memory range specified by > HostAddress and Pages > + was not allocated with AllocateBuffer(). > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoFreeBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN UINTN Pages, > + IN VOID *HostAddress > + ); > + > +/** > + Flushes all PCI posted write transactions from a PCI host bridge to sy= stem > memory. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + > + @retval EFI_SUCCESS The PCI posted write transactions were f= lushed > from the PCI host > + bridge to system memory. > + @retval EFI_DEVICE_ERROR The PCI posted write transactions were n= ot > flushed from the PCI > + host bridge due to a hardware error. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoFlush ( > + IN EFI_PCI_IO_PROTOCOL *This > + ); > + > +/** > + Retrieves this PCI controller's current PCI bus number, device number,= and > function number. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param SegmentNumber The PCI controller's current PCI segment > number. > + @param BusNumber The PCI controller's current PCI bus num= ber. > + @param DeviceNumber The PCI controller's current PCI device > number. > + @param FunctionNumber The PCI controller's current PCI functio= n > number. > + > + @retval EFI_SUCCESS The PCI controller location was returned= . > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoGetLocation ( > + IN EFI_PCI_IO_PROTOCOL *This, > + OUT UINTN *Segment, > + OUT UINTN *Bus, > + OUT UINTN *Device, > + OUT UINTN *Function > + ); > + > +/** > + Check BAR type for PCI resource. > + > + @param PciIoDevice PCI device instance. > + @param BarIndex The BAR index of the standard PCI Configuration > header to use as the > + base address for the memory or I/O operation to p= erform. > + @param BarType Memory or I/O. > + > + @retval TRUE Pci device's bar type is same with input BarType. > + @retval TRUE Pci device's bar type is not same with input BarT= ype. > + > +**/ > +BOOLEAN > +CheckBarType ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT8 BarIndex, > + IN PCI_BAR_TYPE BarType > + ); > + > +/** > + Set/Disable new attributes to a Root Bridge. > + > + @param PciIoDevice Pci device instance. > + @param Attributes New attribute want to be set. > + @param Operation Set or Disable. > + > + @retval EFI_UNSUPPORTED If root bridge does not support change > attribute. > + @retval EFI_SUCCESS Successfully set new attributes. > + > +**/ > +EFI_STATUS > +ModifyRootBridgeAttributes ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN UINT64 Attributes, > + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation > + ); > + > +/** > + Check whether this device can be enable/disable to snoop. > + > + @param PciIoDevice Pci device instance. > + @param Operation Enable/Disable. > + > + @retval EFI_UNSUPPORTED Pci device is not GFX device or not support > snoop. > + @retval EFI_SUCCESS Snoop can be supported. > + > +**/ > +EFI_STATUS > +SupportPaletteSnoopAttributes ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation > + ); > + > +/** > + Performs an operation on the attributes that this PCI controller suppo= rts. > The operations include > + getting the set of supported attributes, retrieving the current attrib= utes, > setting the current > + attributes, enabling attributes, and disabling attributes. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Operation The operation to perform on the attribut= es for > this PCI controller. > + @param Attributes The mask of attributes that are used for= Set, > Enable, and Disable > + operations. > + @param Result A pointer to the result mask of attribut= es that are > returned for the Get > + and Supported operations. > + > + @retval EFI_SUCCESS The operation on the PCI controller's at= tributes > was completed. > + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. > + @retval EFI_UNSUPPORTED one or more of the bits set in > + Attributes are not supported by this PCI= controller or one of > + its parent bridges when Operation is Set= , Enable or Disable. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoAttributes ( > + IN EFI_PCI_IO_PROTOCOL * This, > + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, > + IN UINT64 Attributes, > + OUT UINT64 *Result OPTIONAL > + ); > + > +/** > + Gets the attributes that this PCI controller supports setting on a BAR= using > + SetBarAttributes(), and retrieves the list of resource descriptors for= a BAR. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for resource range. The leg= al range for this > field is 0..5. > + @param Supports A pointer to the mask of attributes that= this PCI > controller supports > + setting for this BAR with SetBarAttribut= es(). > + @param Resources A pointer to the resource descriptors th= at > describe the current > + configuration of this BAR of the PCI con= troller. > + > + @retval EFI_SUCCESS If Supports is not NULL, then the attrib= utes that > the PCI > + controller supports are returned in Supp= orts. If Resources > + is not NULL, then the resource descripto= rs that the PCI > + controller is currently using are return= ed in Resources. > + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_OUT_OF_RESOURCES There are not enough resources > available to allocate > + Resources. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoGetBarAttributes ( > + IN EFI_PCI_IO_PROTOCOL * This, > + IN UINT8 BarIndex, > + OUT UINT64 *Supports, OPTIONAL > + OUT VOID **Resources OPTIONAL > + ); > + > +/** > + Sets the attributes for a range of a BAR on a PCI controller. > + > + @param This A pointer to the EFI_PCI_IO_PROTOCOL ins= tance. > + @param Attributes The mask of attributes to set for the re= source > range specified by > + BarIndex, Offset, and Length. > + @param BarIndex The BAR index of the standard PCI Config= uration > header to use as the > + base address for resource range. The leg= al range for this > field is 0..5. > + @param Offset A pointer to the BAR relative base addre= ss of the > resource range to be > + modified by the attributes specified by = Attributes. > + @param Length A pointer to the length of the resource = range to > be modified by the > + attributes specified by Attributes. > + > + @retval EFI_SUCCESS The set of attributes specified by Attri= butes for > the resource > + range specified by BarIndex, Offset, and= Length were > + set on the PCI controller, and the actua= l resource range is > returned > + in Offset and Length. > + @retval EFI_INVALID_PARAMETER Offset or Length is NULL. > + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controll= er. > + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set > the attributes on the > + resource range specified by BarIndex, Of= fset, and > + Length. > + > +**/ > +EFI_STATUS > +EFIAPI > +PciIoSetBarAttributes ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN UINT64 Attributes, > + IN UINT8 BarIndex, > + IN OUT UINT64 *Offset, > + IN OUT UINT64 *Length > + ); > + > + > +/** > + Test whether two Pci devices has same parent bridge. > + > + @param PciDevice1 The first pci device for testing. > + @param PciDevice2 The second pci device for testing. > + > + @retval TRUE Two Pci device has the same parent bridge. > + @retval FALSE Two Pci device has not the same parent bridge. > + > +**/ > +BOOLEAN > +PciDevicesOnTheSamePath ( > + IN PCI_IO_DEVICE *PciDevice1, > + IN PCI_IO_DEVICE *PciDevice2 > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciLib.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciLib.c > new file mode 100644 > index 0000000000..2b76100740 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciLib.c > @@ -0,0 +1,1809 @@ > +/** @file > + Internal library implementation for PCI Bus module. > + > +Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
> +(C) Copyright 2015 Hewlett Packard Enterprise Development LP
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +GLOBAL_REMOVE_IF_UNREFERENCED > +CHAR16 *mBarTypeStr[] =3D { > + L"Unknow", > + L" Io16", > + L" Io32", > + L" Mem32", > + L"PMem32", > + L" Mem64", > + L"PMem64", > + L" OpRom", > + L" Io", > + L" Mem", > + L"Unknow" > + }; > + > +/** > + Retrieve the max bus number that is assigned to the Root Bridge hierar= chy. > + It can support the case that there are multiple bus ranges. > + > + @param Bridge Bridge device instance. > + > + @retval The max bus number that is assigned to this R= oot Bridge > hierarchy. > + > +**/ > +UINT16 > +PciGetMaxBusNumber ( > + IN PCI_IO_DEVICE *Bridge > + ) > +{ > + PCI_IO_DEVICE *RootBridge; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges; > + UINT64 MaxNumberInRange; > + > + // > + // Get PCI Root Bridge device > + // > + RootBridge =3D Bridge; > + while (RootBridge->Parent !=3D NULL) { > + RootBridge =3D RootBridge->Parent; > + } > + MaxNumberInRange =3D 0; > + // > + // Iterate the bus number ranges to get max PCI bus number > + // > + BusNumberRanges =3D RootBridge->BusNumberRanges; > + while (BusNumberRanges->Desc !=3D ACPI_END_TAG_DESCRIPTOR) { > + MaxNumberInRange =3D BusNumberRanges->AddrRangeMin + > BusNumberRanges->AddrLen - 1; > + BusNumberRanges++; > + } > + return (UINT16) MaxNumberInRange; > +} > + > +/** > + Retrieve the PCI Card device BAR information via PciIo interface. > + > + @param PciIoDevice PCI Card device instance. > + > +**/ > +VOID > +GetBackPcCardBar ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + UINT32 Address; > + > + if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + return; > + } > + > + // > + // Read PciBar information from the bar register > + // > + if (!gFullEnumeration) { > + Address =3D 0; > + PciIoDevice->PciIo.Pci.Read ( > + &(PciIoDevice->PciIo), > + EfiPciIoWidthUint32, > + PCI_CARD_MEMORY_BASE_0, > + 1, > + &Address > + ); > + > + (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress =3D (UINT64) (Address)= ; > + (PciIoDevice->PciBar)[P2C_MEM_1].Length =3D 0x2000000; > + (PciIoDevice->PciBar)[P2C_MEM_1].BarType =3D PciBarTypeMem32; > + > + Address =3D 0; > + PciIoDevice->PciIo.Pci.Read ( > + &(PciIoDevice->PciIo), > + EfiPciIoWidthUint32, > + PCI_CARD_MEMORY_BASE_1, > + 1, > + &Address > + ); > + (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress =3D (UINT64) (Address)= ; > + (PciIoDevice->PciBar)[P2C_MEM_2].Length =3D 0x2000000; > + (PciIoDevice->PciBar)[P2C_MEM_2].BarType =3D PciBarTypePMem32; > + > + Address =3D 0; > + PciIoDevice->PciIo.Pci.Read ( > + &(PciIoDevice->PciIo), > + EfiPciIoWidthUint32, > + PCI_CARD_IO_BASE_0_LOWER, > + 1, > + &Address > + ); > + (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress =3D (UINT64) (Address); > + (PciIoDevice->PciBar)[P2C_IO_1].Length =3D 0x100; > + (PciIoDevice->PciBar)[P2C_IO_1].BarType =3D PciBarTypeIo16; > + > + Address =3D 0; > + PciIoDevice->PciIo.Pci.Read ( > + &(PciIoDevice->PciIo), > + EfiPciIoWidthUint32, > + PCI_CARD_IO_BASE_1_LOWER, > + 1, > + &Address > + ); > + (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress =3D (UINT64) (Address); > + (PciIoDevice->PciBar)[P2C_IO_2].Length =3D 0x100; > + (PciIoDevice->PciBar)[P2C_IO_2].BarType =3D PciBarTypeIo16; > + > + } > + > + if (gPciHotPlugInit !=3D NULL && FeaturePcdGet > (PcdPciBusHotplugDeviceSupport)) { > + GetResourcePaddingForHpb (PciIoDevice); > + } > +} > + > +/** > + Remove rejected pci device from specific root bridge > + handle. > + > + @param RootBridgeHandle Specific parent root bridge handle. > + @param Bridge Bridge device instance. > + > +**/ > +VOID > +RemoveRejectedPciDevices ( > + IN EFI_HANDLE RootBridgeHandle, > + IN PCI_IO_DEVICE *Bridge > + ) > +{ > + PCI_IO_DEVICE *Temp; > + LIST_ENTRY *CurrentLink; > + LIST_ENTRY *LastLink; > + > + if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + return; > + } > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (IS_PCI_BRIDGE (&Temp->Pci)) { > + // > + // Remove rejected devices recusively > + // > + RemoveRejectedPciDevices (RootBridgeHandle, Temp); > + } else { > + // > + // Skip rejection for all PPBs, while detect rejection for others > + // > + if (IsPciDeviceRejected (Temp)) { > + > + // > + // For P2C, remove all devices on it > + // > + if (!IsListEmpty (&Temp->ChildList)) { > + RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp); > + } > + > + // > + // Finally remove itself > + // > + LastLink =3D CurrentLink->BackLink; > + RemoveEntryList (CurrentLink); > + FreePciDevice (Temp); > + > + CurrentLink =3D LastLink; > + } > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > +} > + > +/** > + Dump the resourc map of the bridge device. > + > + @param[in] BridgeResource Resource descriptor of the bridge device. > +**/ > +VOID > +DumpBridgeResource ( > + IN PCI_RESOURCE_NODE *BridgeResource > + ) > +{ > + LIST_ENTRY *Link; > + PCI_RESOURCE_NODE *Resource; > + PCI_BAR *Bar; > + > + if ((BridgeResource !=3D NULL) && (BridgeResource->Length !=3D 0)) { > + DEBUG (( > + EFI_D_INFO, "Type =3D %s; Base =3D 0x%lx;\tLength =3D 0x%lx;\tAlig= nment =3D > 0x%lx\n", > + mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)], > + BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress, > + BridgeResource->Length, BridgeResource->Alignment > + )); > + for ( Link =3D GetFirstNode (&BridgeResource->ChildList) > + ; !IsNull (&BridgeResource->ChildList, Link) > + ; Link =3D GetNextNode (&BridgeResource->ChildList, Link) > + ) { > + Resource =3D RESOURCE_NODE_FROM_LINK (Link); > + if (Resource->ResourceUsage =3D=3D PciResUsageTypical) { > + Bar =3D Resource->Virtual ? Resource->PciDev->VfPciBar : Resourc= e- > >PciDev->PciBar; > + DEBUG (( > + EFI_D_INFO, " Base =3D 0x%lx;\tLength =3D 0x%lx;\tAlignment = =3D > 0x%lx;\tOwner =3D %s [%02x|%02x|%02x:", > + Bar[Resource->Bar].BaseAddress, Resource->Length, Resource- > >Alignment, > + IS_PCI_BRIDGE (&Resource->PciDev->Pci) ? L"PPB" : > + IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" : > + L"PCI", > + Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber, > + Resource->PciDev->FunctionNumber > + )); > + > + if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && > !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) || > + (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < > PPB_IO_RANGE)) || > + (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Ba= r > < P2C_MEM_1)) > + ) { > + // > + // The resource requirement comes from the device itself. > + // > + DEBUG ((EFI_D_INFO, "%02x]", Bar[Resource->Bar].Offset)); > + } else { > + // > + // The resource requirement comes from the subordinate devices= . > + // > + DEBUG ((EFI_D_INFO, "**]")); > + } > + } else { > + DEBUG ((EFI_D_INFO, " Base =3D Padding;\tLength =3D 0x%lx;\tAl= ignment > =3D 0x%lx", Resource->Length, Resource->Alignment)); > + } > + if (BridgeResource->ResType !=3D Resource->ResType) { > + DEBUG ((EFI_D_INFO, "; Type =3D %s", mBarTypeStr[MIN (Resource- > >ResType, PciBarTypeMaxType)])); > + } > + DEBUG ((EFI_D_INFO, "\n")); > + } > + } > +} > + > +/** > + Find the corresponding resource node for the Device in child list of > BridgeResource. > + > + @param[in] Device Pointer to PCI_IO_DEVICE. > + @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE. > + @param[out] DeviceResources Pointer to a buffer to receive resources f= or > the Device. > + > + @return Count of the resource descriptors returned. > +**/ > +UINTN > +FindResourceNode ( > + IN PCI_IO_DEVICE *Device, > + IN PCI_RESOURCE_NODE *BridgeResource, > + OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL > + ) > +{ > + LIST_ENTRY *Link; > + PCI_RESOURCE_NODE *Resource; > + UINTN Count; > + > + Count =3D 0; > + for ( Link =3D BridgeResource->ChildList.ForwardLink > + ; Link !=3D &BridgeResource->ChildList > + ; Link =3D Link->ForwardLink > + ) { > + Resource =3D RESOURCE_NODE_FROM_LINK (Link); > + if (Resource->PciDev =3D=3D Device) { > + if (DeviceResources !=3D NULL) { > + DeviceResources[Count] =3D Resource; > + } > + Count++; > + } > + } > + > + return Count; > +} > + > +/** > + Dump the resource map of all the devices under Bridge. > + > + @param[in] Bridge Bridge device instance. > + @param[in] Resources Resource descriptors for the bridge device. > + @param[in] ResourceCount Count of resource descriptors. > +**/ > +VOID > +DumpResourceMap ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_RESOURCE_NODE **Resources, > + IN UINTN ResourceCount > + ) > +{ > + EFI_STATUS Status; > + LIST_ENTRY *Link; > + PCI_IO_DEVICE *Device; > + UINTN Index; > + CHAR16 *Str; > + PCI_RESOURCE_NODE **ChildResources; > + UINTN ChildResourceCount; > + > + DEBUG ((EFI_D_INFO, "PciBus: Resource Map for ")); > + > + Status =3D gBS->OpenProtocol ( > + Bridge->Handle, > + &gEfiPciRootBridgeIoProtocolGuid, > + NULL, > + NULL, > + NULL, > + EFI_OPEN_PROTOCOL_TEST_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n", > + Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber > + )); > + } else { > + Str =3D ConvertDevicePathToText ( > + DevicePathFromHandle (Bridge->Handle), > + FALSE, > + FALSE > + ); > + DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str !=3D NULL ? Str : L"")); > + if (Str !=3D NULL) { > + FreePool (Str); > + } > + } > + > + for (Index =3D 0; Index < ResourceCount; Index++) { > + DumpBridgeResource (Resources[Index]); > + } > + DEBUG ((EFI_D_INFO, "\n")); > + > + for ( Link =3D Bridge->ChildList.ForwardLink > + ; Link !=3D &Bridge->ChildList > + ; Link =3D Link->ForwardLink > + ) { > + Device =3D PCI_IO_DEVICE_FROM_LINK (Link); > + if (IS_PCI_BRIDGE (&Device->Pci)) { > + > + ChildResourceCount =3D 0; > + for (Index =3D 0; Index < ResourceCount; Index++) { > + ChildResourceCount +=3D FindResourceNode (Device, Resources[Inde= x], > NULL); > + } > + ChildResources =3D AllocatePool (sizeof (PCI_RESOURCE_NODE *) * > ChildResourceCount); > + ASSERT (ChildResources !=3D NULL); > + ChildResourceCount =3D 0; > + for (Index =3D 0; Index < ResourceCount; Index++) { > + ChildResourceCount +=3D FindResourceNode (Device, Resources[Inde= x], > &ChildResources[ChildResourceCount]); > + } > + > + DumpResourceMap (Device, ChildResources, ChildResourceCount); > + FreePool (ChildResources); > + } > + } > +} > + > +/** > + Adjust the Devices' BAR size to minimum value if it support Resizeable= BAR > capability. > + > + @param RootBridgeDev Pointer to instance of PCI_IO_DEVICE.. > + > + @return TRUE if BAR size is adjusted. > + > +**/ > +BOOLEAN > +AdjustPciDeviceBarSize ( > + IN PCI_IO_DEVICE *RootBridgeDev > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + LIST_ENTRY *CurrentLink; > + BOOLEAN Adjusted; > + UINTN Offset; > + UINTN BarIndex; > + > + Adjusted =3D FALSE; > + CurrentLink =3D RootBridgeDev->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &RootBridgeDev->Child= List) > { > + PciIoDevice =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { > + if (AdjustPciDeviceBarSize (PciIoDevice)) { > + Adjusted =3D TRUE; > + } > + } else { > + if (PciIoDevice->ResizableBarOffset !=3D 0) { > + DEBUG (( > + DEBUG_ERROR, > + "PciBus: [%02x|%02x|%02x] Adjust Pci Device Bar Size\n", > + PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice= - > >FunctionNumber > + )); > + PciProgramResizableBar (PciIoDevice, PciResizableBarMin); > + // > + // Start to parse the bars > + // > + for (Offset =3D 0x10, BarIndex =3D 0; Offset <=3D 0x24 && BarInd= ex < > PCI_MAX_BAR; BarIndex++) { > + Offset =3D PciParseBar (PciIoDevice, Offset, BarIndex); > + } > + Adjusted =3D TRUE; > + DEBUG_CODE (DumpPciBars (PciIoDevice);); > + } > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return Adjusted; > +} > + > +/** > + Submits the I/O and memory resource requirements for the specified PCI > Host Bridge. > + > + @param PciResAlloc Point to protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + > + @retval EFI_SUCCESS Successfully finished resource allocatio= n. > + @retval EFI_NOT_FOUND Cannot get root bridge instance. > + @retval EFI_OUT_OF_RESOURCES Platform failed to program the > resources if no hot plug supported. > + @retval other Some error occurred when allocating reso= urces for > the PCI Host Bridge. > + > + @note Feature flag PcdPciBusHotplugDeviceSupport determine whether > need support hotplug. > + > +**/ > +EFI_STATUS > +PciHostBridgeResourceAllocator ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ) > +{ > + PCI_IO_DEVICE *RootBridgeDev; > + EFI_HANDLE RootBridgeHandle; > + VOID *AcpiConfig; > + EFI_STATUS Status; > + UINT64 IoBase; > + UINT64 Mem32Base; > + UINT64 PMem32Base; > + UINT64 Mem64Base; > + UINT64 PMem64Base; > + UINT64 IoResStatus; > + UINT64 Mem32ResStatus; > + UINT64 PMem32ResStatus; > + UINT64 Mem64ResStatus; > + UINT64 PMem64ResStatus; > + UINT32 MaxOptionRomSize; > + PCI_RESOURCE_NODE *IoBridge; > + PCI_RESOURCE_NODE *Mem32Bridge; > + PCI_RESOURCE_NODE *PMem32Bridge; > + PCI_RESOURCE_NODE *Mem64Bridge; > + PCI_RESOURCE_NODE *PMem64Bridge; > + PCI_RESOURCE_NODE IoPool; > + PCI_RESOURCE_NODE Mem32Pool; > + PCI_RESOURCE_NODE PMem32Pool; > + PCI_RESOURCE_NODE Mem64Pool; > + PCI_RESOURCE_NODE PMem64Pool; > + EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD > HandleExtendedData; > + EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD > AllocFailExtendedData; > + BOOLEAN ResizableBarNeedAdjust; > + BOOLEAN ResizableBarAdjusted; > + > + ResizableBarNeedAdjust =3D PcdGetBool (PcdPcieResizableBarSupport); > + > + // > + // It may try several times if the resource allocation fails > + // > + while (TRUE) { > + // > + // Initialize resource pool > + // > + InitializeResourcePool (&IoPool, PciBarTypeIo16); > + InitializeResourcePool (&Mem32Pool, PciBarTypeMem32); > + InitializeResourcePool (&PMem32Pool, PciBarTypePMem32); > + InitializeResourcePool (&Mem64Pool, PciBarTypeMem64); > + InitializeResourcePool (&PMem64Pool, PciBarTypePMem64); > + > + RootBridgeDev =3D NULL; > + RootBridgeHandle =3D 0; > + > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, > &RootBridgeHandle) =3D=3D EFI_SUCCESS) { > + // > + // Get Root Bridge Device by handle > + // > + RootBridgeDev =3D GetRootBridgeByHandle (RootBridgeHandle); > + > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Create the entire system resource map from the information coll= ected > by > + // enumerator. Several resource tree was created > + // > + > + // > + // If non-standard PCI Bridge I/O window alignment is supported, > + // set I/O aligment to minimum possible alignment for root bridge. > + // > + IoBridge =3D CreateResourceNode ( > + RootBridgeDev, > + 0, > + FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF:= 0xFFF, > + RB_IO_RANGE, > + PciBarTypeIo16, > + PciResUsageTypical > + ); > + > + Mem32Bridge =3D CreateResourceNode ( > + RootBridgeDev, > + 0, > + 0xFFFFF, > + RB_MEM32_RANGE, > + PciBarTypeMem32, > + PciResUsageTypical > + ); > + > + PMem32Bridge =3D CreateResourceNode ( > + RootBridgeDev, > + 0, > + 0xFFFFF, > + RB_PMEM32_RANGE, > + PciBarTypePMem32, > + PciResUsageTypical > + ); > + > + Mem64Bridge =3D CreateResourceNode ( > + RootBridgeDev, > + 0, > + 0xFFFFF, > + RB_MEM64_RANGE, > + PciBarTypeMem64, > + PciResUsageTypical > + ); > + > + PMem64Bridge =3D CreateResourceNode ( > + RootBridgeDev, > + 0, > + 0xFFFFF, > + RB_PMEM64_RANGE, > + PciBarTypePMem64, > + PciResUsageTypical > + ); > + > + // > + // Get the max ROM size that the root bridge can process > + // Insert to resource map so that there will be dedicate MEM32 res= ource > range for Option ROM. > + // All devices' Option ROM share the same MEM32 resource. > + // > + MaxOptionRomSize =3D GetMaxOptionRomSize (RootBridgeDev); > + if (MaxOptionRomSize !=3D 0) { > + RootBridgeDev->PciBar[0].BarType =3D PciBarTypeOpRom; > + RootBridgeDev->PciBar[0].Length =3D MaxOptionRomSize; > + RootBridgeDev->PciBar[0].Alignment =3D MaxOptionRomSize - 1; > + GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, > PMem32Bridge, Mem64Bridge, PMem64Bridge); > + } > + > + // > + // Create resourcemap by going through all the devices subject to = this > root bridge > + // > + CreateResourceMap ( > + RootBridgeDev, > + IoBridge, > + Mem32Bridge, > + PMem32Bridge, > + Mem64Bridge, > + PMem64Bridge > + ); > + > + // > + // Based on the all the resource tree, construct ACPI resource nod= e to > + // submit the resource aperture to pci host bridge protocol > + // > + Status =3D ConstructAcpiResourceRequestor ( > + RootBridgeDev, > + IoBridge, > + Mem32Bridge, > + PMem32Bridge, > + Mem64Bridge, > + PMem64Bridge, > + &AcpiConfig > + ); > + > + // > + // Insert these resource nodes into the database > + // > + InsertResourceNode (&IoPool, IoBridge); > + InsertResourceNode (&Mem32Pool, Mem32Bridge); > + InsertResourceNode (&PMem32Pool, PMem32Bridge); > + InsertResourceNode (&Mem64Pool, Mem64Bridge); > + InsertResourceNode (&PMem64Pool, PMem64Bridge); > + > + if (Status =3D=3D EFI_SUCCESS) { > + // > + // Submit the resource requirement > + // > + Status =3D PciResAlloc->SubmitResources ( > + PciResAlloc, > + RootBridgeDev->Handle, > + AcpiConfig > + ); > + // > + // If SubmitResources returns error, PciBus isn't able to start. > + // It's a fatal error so assertion is added. > + // > + DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\= n", > Status)); > + ASSERT_EFI_ERROR (Status); > + } > + > + // > + // Free acpi resource node > + // > + if (AcpiConfig !=3D NULL) { > + FreePool (AcpiConfig); > + } > + > + if (EFI_ERROR (Status)) { > + // > + // Destroy all the resource tree > + // > + DestroyResourceTree (&IoPool); > + DestroyResourceTree (&Mem32Pool); > + DestroyResourceTree (&PMem32Pool); > + DestroyResourceTree (&Mem64Pool); > + DestroyResourceTree (&PMem64Pool); > + return Status; > + } > + } > + // > + // End while, at least one Root Bridge should be found. > + // > + ASSERT (RootBridgeDev !=3D NULL); > + > + // > + // Notify platform to start to program the resource > + // > + Status =3D NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResourc= es); > + DEBUG ((EFI_D_INFO, "PciBus: HostBridge- > >NotifyPhase(AllocateResources) - %r\n", Status)); > + if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + // > + // If Hot Plug is not supported > + // > + if (EFI_ERROR (Status)) { > + // > + // Allocation failed, then return > + // > + return EFI_OUT_OF_RESOURCES; > + } > + // > + // Allocation succeed. > + // Get host bridge handle for status report, and then skip the mai= n while > + // > + HandleExtendedData.Handle =3D RootBridgeDev->PciRootBridgeIo- > >ParentHandle; > + > + break; > + > + } else { > + // > + // If Hot Plug is supported > + // > + if (!EFI_ERROR (Status)) { > + // > + // Allocation succeed, then continue the following > + // > + break; > + } > + > + // > + // If the resource allocation is unsuccessful, free resources on b= ridge > + // > + > + RootBridgeDev =3D NULL; > + RootBridgeHandle =3D 0; > + > + IoResStatus =3D EFI_RESOURCE_SATISFIED; > + Mem32ResStatus =3D EFI_RESOURCE_SATISFIED; > + PMem32ResStatus =3D EFI_RESOURCE_SATISFIED; > + Mem64ResStatus =3D EFI_RESOURCE_SATISFIED; > + PMem64ResStatus =3D EFI_RESOURCE_SATISFIED; > + > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, > &RootBridgeHandle) =3D=3D EFI_SUCCESS) { > + // > + // Get RootBridg Device by handle > + // > + RootBridgeDev =3D GetRootBridgeByHandle (RootBridgeHandle); > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Get host bridge handle for status report > + // > + HandleExtendedData.Handle =3D RootBridgeDev->PciRootBridgeIo- > >ParentHandle; > + > + // > + // Get acpi resource node for all the resource types > + // > + AcpiConfig =3D NULL; > + > + Status =3D PciResAlloc->GetProposedResources ( > + PciResAlloc, > + RootBridgeDev->Handle, > + &AcpiConfig > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (AcpiConfig !=3D NULL) { > + // > + // Adjust resource allocation policy for each RB > + // > + GetResourceAllocationStatus ( > + AcpiConfig, > + &IoResStatus, > + &Mem32ResStatus, > + &PMem32ResStatus, > + &Mem64ResStatus, > + &PMem64ResStatus > + ); > + FreePool (AcpiConfig); > + } > + } > + // > + // End while > + // > + > + // > + // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code > + // > + // > + // It is very difficult to follow the spec here > + // Device path , Bar index can not be get here > + // > + ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData)); > + > + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( > + EFI_PROGRESS_CODE, > + EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT, > + (VOID *) &AllocFailExtendedData, > + sizeof (AllocFailExtendedData) > + ); > + > + // > + // When resource conflict happens, adjust the BAR size first. > + // Only when adjusting BAR size doesn't help or BAR size cannot be > adjusted, > + // reject the device who requests largest resource that causes conf= lict. > + // > + ResizableBarAdjusted =3D FALSE; > + if (ResizableBarNeedAdjust) { > + ResizableBarAdjusted =3D AdjustPciDeviceBarSize (RootBridgeDev); > + ResizableBarNeedAdjust =3D FALSE; > + } > + if (!ResizableBarAdjusted) { > + Status =3D PciHostBridgeAdjustAllocation ( > + &IoPool, > + &Mem32Pool, > + &PMem32Pool, > + &Mem64Pool, > + &PMem64Pool, > + IoResStatus, > + Mem32ResStatus, > + PMem32ResStatus, > + Mem64ResStatus, > + PMem64ResStatus > + ); > + } > + // > + // Destroy all the resource tree > + // > + DestroyResourceTree (&IoPool); > + DestroyResourceTree (&Mem32Pool); > + DestroyResourceTree (&PMem32Pool); > + DestroyResourceTree (&Mem64Pool); > + DestroyResourceTree (&PMem64Pool); > + > + NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + } > + // > + // End main while > + // > + > + // > + // Raise the EFI_IOB_PCI_RES_ALLOC status code > + // > + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( > + EFI_PROGRESS_CODE, > + EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC, > + (VOID *) &HandleExtendedData, > + sizeof (HandleExtendedData) > + ); > + > + // > + // Notify pci bus driver starts to program the resource > + // > + Status =3D NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + RootBridgeDev =3D NULL; > + > + RootBridgeHandle =3D 0; > + > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) > =3D=3D EFI_SUCCESS) { > + // > + // Get RootBridg Device by handle > + // > + RootBridgeDev =3D GetRootBridgeByHandle (RootBridgeHandle); > + > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Get acpi resource node for all the resource types > + // > + AcpiConfig =3D NULL; > + Status =3D PciResAlloc->GetProposedResources ( > + PciResAlloc, > + RootBridgeDev->Handle, > + &AcpiConfig > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Get the resource base by interpreting acpi resource node > + // > + // > + GetResourceBase ( > + AcpiConfig, > + &IoBase, > + &Mem32Base, > + &PMem32Base, > + &Mem64Base, > + &PMem64Base > + ); > + > + // > + // Create the entire system resource map from the information collec= ted > by > + // enumerator. Several resource tree was created > + // > + FindResourceNode (RootBridgeDev, &IoPool, &IoBridge); > + FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge); > + FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge); > + FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge); > + FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge); > + > + ASSERT (IoBridge !=3D NULL); > + ASSERT (Mem32Bridge !=3D NULL); > + ASSERT (PMem32Bridge !=3D NULL); > + ASSERT (Mem64Bridge !=3D NULL); > + ASSERT (PMem64Bridge !=3D NULL); > + > + // > + // Program IO resources > + // > + ProgramResource ( > + IoBase, > + IoBridge > + ); > + > + // > + // Program Mem32 resources > + // > + ProgramResource ( > + Mem32Base, > + Mem32Bridge > + ); > + > + // > + // Program PMem32 resources > + // > + ProgramResource ( > + PMem32Base, > + PMem32Bridge > + ); > + > + // > + // Program Mem64 resources > + // > + ProgramResource ( > + Mem64Base, > + Mem64Bridge > + ); > + > + // > + // Program PMem64 resources > + // > + ProgramResource ( > + PMem64Base, > + PMem64Bridge > + ); > + > + // > + // Process Option ROM for this root bridge after all BARs are > programmed. > + // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM > BAR Base in order to > + // shadow the Option ROM of the devices under the PPB. > + // After the shadow, Option ROM BAR decoding is turned off and the > PPB's MEM32 RANGE > + // BAR is restored back to the original value. > + // The original value is programmed by ProgramResource() above. > + // > + DEBUG (( > + DEBUG_INFO, "Process Option ROM: BAR Base/Length =3D %lx/%lx\n", > + RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev- > >PciBar[0].Length > + )); > + ProcessOptionRom (RootBridgeDev, RootBridgeDev- > >PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length); > + > + IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress =3D IoBa= se; > + Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress =3D > Mem32Base; > + PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress =3D > PMem32Base; > + Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress =3D > Mem64Base; > + PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress =3D > PMem64Base; > + > + // > + // Dump the resource map for current root bridge > + // > + DEBUG_CODE ( > + PCI_RESOURCE_NODE *Resources[5]; > + Resources[0] =3D IoBridge; > + Resources[1] =3D Mem32Bridge; > + Resources[2] =3D PMem32Bridge; > + Resources[3] =3D Mem64Bridge; > + Resources[4] =3D PMem64Bridge; > + DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE > (Resources)); > + ); > + > + FreePool (AcpiConfig); > + } > + > + // > + // Destroy all the resource tree > + // > + DestroyResourceTree (&IoPool); > + DestroyResourceTree (&Mem32Pool); > + DestroyResourceTree (&PMem32Pool); > + DestroyResourceTree (&Mem64Pool); > + DestroyResourceTree (&PMem64Pool); > + > + // > + // Notify the resource allocation phase is to end > + // > + Status =3D NotifyPhase (PciResAlloc, > EfiPciHostBridgeEndResourceAllocation); > + > + return Status; > +} > + > +/** > + Allocate NumberOfBuses buses and return the next available PCI bus > number. > + > + @param Bridge Bridge device instance. > + @param StartBusNumber Current available PCI bus number. > + @param NumberOfBuses Number of buses enumerated below the > StartBusNumber. > + @param NextBusNumber Next available PCI bus number. > + > + @retval EFI_SUCCESS Available bus number resource is enough.= Next > available PCI bus number > + is returned in NextBusNumber. > + @retval EFI_OUT_OF_RESOURCES Available bus number resource is not > enough for allocation. > + > +**/ > +EFI_STATUS > +PciAllocateBusNumber ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber, > + IN UINT8 NumberOfBuses, > + OUT UINT8 *NextBusNumber > + ) > +{ > + PCI_IO_DEVICE *RootBridge; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges; > + UINT8 NextNumber; > + UINT64 MaxNumberInRange; > + > + // > + // Get PCI Root Bridge device > + // > + RootBridge =3D Bridge; > + while (RootBridge->Parent !=3D NULL) { > + RootBridge =3D RootBridge->Parent; > + } > + > + // > + // Get next available PCI bus number > + // > + BusNumberRanges =3D RootBridge->BusNumberRanges; > + while (BusNumberRanges->Desc !=3D ACPI_END_TAG_DESCRIPTOR) { > + MaxNumberInRange =3D BusNumberRanges->AddrRangeMin + > BusNumberRanges->AddrLen - 1; > + if (StartBusNumber >=3D BusNumberRanges->AddrRangeMin && > StartBusNumber <=3D MaxNumberInRange) { > + NextNumber =3D (UINT8)(StartBusNumber + NumberOfBuses); > + while (NextNumber > MaxNumberInRange) { > + ++BusNumberRanges; > + if (BusNumberRanges->Desc =3D=3D ACPI_END_TAG_DESCRIPTOR) { > + return EFI_OUT_OF_RESOURCES; > + } > + NextNumber =3D (UINT8)(NextNumber + (BusNumberRanges- > >AddrRangeMin - (MaxNumberInRange + 1))); > + MaxNumberInRange =3D BusNumberRanges->AddrRangeMin + > BusNumberRanges->AddrLen - 1; > + } > + *NextBusNumber =3D NextNumber; > + return EFI_SUCCESS; > + } > + BusNumberRanges++; > + } > + return EFI_OUT_OF_RESOURCES; > +} > + > +/** > + Scan pci bus and assign bus number to the given PCI bus system. > + > + @param Bridge Bridge device instance. > + @param StartBusNumber start point. > + @param SubBusNumber Point to sub bus number. > + @param PaddedBusRange Customized bus number. > + > + @retval EFI_SUCCESS Successfully scanned and assigned bus number. > + @retval other Some error occurred when scanning pci bus. > + > + @note Feature flag PcdPciBusHotplugDeviceSupport determine whether > need support hotplug. > + > +**/ > +EFI_STATUS > +PciScanBus ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber, > + OUT UINT8 *SubBusNumber, > + OUT UINT8 *PaddedBusRange > + ) > +{ > + EFI_STATUS Status; > + PCI_TYPE00 Pci; > + UINT8 Device; > + UINT8 Func; > + UINT64 Address; > + UINT8 SecondBus; > + UINT8 PaddedSubBus; > + UINT16 Register; > + UINTN HpIndex; > + PCI_IO_DEVICE *PciDevice; > + EFI_EVENT Event; > + EFI_HPC_STATE State; > + UINT64 PciAddress; > + EFI_HPC_PADDING_ATTRIBUTES Attributes; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *NextDescriptors; > + UINT16 BusRange; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + BOOLEAN BusPadding; > + UINT32 TempReservedBusNum; > + > + PciRootBridgeIo =3D Bridge->PciRootBridgeIo; > + SecondBus =3D 0; > + Register =3D 0; > + State =3D 0; > + Attributes =3D (EFI_HPC_PADDING_ATTRIBUTES) 0; > + BusRange =3D 0; > + BusPadding =3D FALSE; > + PciDevice =3D NULL; > + PciAddress =3D 0; > + > + for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) { > + TempReservedBusNum =3D 0; > + for (Func =3D 0; Func <=3D PCI_MAX_FUNC; Func++) { > + > + // > + // Check to see whether a pci device is present > + // > + Status =3D PciDevicePresent ( > + PciRootBridgeIo, > + &Pci, > + StartBusNumber, > + Device, > + Func > + ); > + > + if (EFI_ERROR (Status) && Func =3D=3D 0) { > + // > + // go to next device if there is no Function 0 > + // > + break; > + } > + > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + // > + // Get the PCI device information > + // > + Status =3D PciSearchDevice ( > + Bridge, > + &Pci, > + StartBusNumber, > + Device, > + Func, > + &PciDevice > + ); > + > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + PciAddress =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0); > + > + if (!IS_PCI_BRIDGE (&Pci)) { > + // > + // PCI bridges will be called later > + // Here just need for PCI device or PCI to cardbus controller > + // EfiPciBeforeChildBusEnumeration for PCI Device Node > + // > + PreprocessController ( > + PciDevice, > + PciDevice->BusNumber, > + PciDevice->DeviceNumber, > + PciDevice->FunctionNumber, > + EfiPciBeforeChildBusEnumeration > + ); > + } > + > + if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + // > + // For Pci Hotplug controller devcie only > + // > + if (gPciHotPlugInit !=3D NULL) { > + // > + // Check if it is a Hotplug PCI controller > + // > + if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpInde= x)) { > + gPciRootHpcData[HpIndex].Found =3D TRUE; > + > + if (!gPciRootHpcData[HpIndex].Initialized) { > + > + Status =3D CreateEventForHpc (HpIndex, &Event); > + > + ASSERT (!EFI_ERROR (Status)); > + > + Status =3D gPciHotPlugInit->InitializeRootHpc ( > + gPciHotPlugInit, > + gPciRootHpcPool[HpIndex].HpcDe= vicePath, > + PciAddress, > + Event, > + &State > + ); > + > + PreprocessController ( > + PciDevice, > + PciDevice->BusNumber, > + PciDevice->DeviceNumber, > + PciDevice->FunctionNumber, > + EfiPciBeforeChildBusEnumeration > + ); > + } > + } > + } > + } > + > + if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) { > + // > + // For PPB > + // > + if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + // > + // If Hot Plug is supported, > + // Get the bridge information > + // > + BusPadding =3D FALSE; > + if (gPciHotPlugInit !=3D NULL) { > + > + if (IsPciHotPlugBus (PciDevice)) { > + > + // > + // If it is initialized, get the padded bus range > + // > + Status =3D gPciHotPlugInit->GetResourcePadding ( > + gPciHotPlugInit, > + PciDevice->DevicePath, > + PciAddress, > + &State, > + (VOID **) &Descriptors, > + &Attributes > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + BusRange =3D 0; > + NextDescriptors =3D Descriptors; > + Status =3D PciGetBusRange ( > + &NextDescriptors, > + NULL, > + NULL, > + &BusRange > + ); > + > + FreePool (Descriptors); > + > + if (!EFI_ERROR (Status)) { > + BusPadding =3D TRUE; > + } else if (Status !=3D EFI_NOT_FOUND) { > + // > + // EFI_NOT_FOUND is not a real error. It indicates no bu= s number > padding requested. > + // > + return Status; > + } > + } > + } > + } > + > + Status =3D PciAllocateBusNumber (Bridge, *SubBusNumber, 1, > SubBusNumber); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + SecondBus =3D *SubBusNumber; > + > + Register =3D (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumb= er); > + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, > PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET); > + > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint16, > + Address, > + 1, > + &Register > + ); > + > + > + // > + // If it is PPB, resursively search down this bridge > + // > + if (IS_PCI_BRIDGE (&Pci)) { > + > + // > + // Temporarily initialize SubBusNumber to maximum bus number t= o > ensure the > + // PCI configuration transaction to go through any PPB > + // > + Register =3D PciGetMaxBusNumber (Bridge); > + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, > PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint8, > + Address, > + 1, > + &Register > + ); > + > + // > + // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige > + // > + PreprocessController ( > + PciDevice, > + PciDevice->BusNumber, > + PciDevice->DeviceNumber, > + PciDevice->FunctionNumber, > + EfiPciBeforeChildBusEnumeration > + ); > + > + Status =3D PciScanBus ( > + PciDevice, > + SecondBus, > + SubBusNumber, > + PaddedBusRange > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding)= { > + // > + // Ensure the device is enabled and initialized > + // > + if ((Attributes =3D=3D EfiPaddingPciRootBridge) && > + (State & EFI_HPC_STATE_ENABLED) !=3D 0 && > + (State & EFI_HPC_STATE_INITIALIZED) !=3D 0) { > + *PaddedBusRange =3D (UINT8) ((UINT8) (BusRange) + > *PaddedBusRange); > + } else { > + // > + // Reserve the larger one between the actual occupied bus nu= mber > and padded bus number > + // > + Status =3D PciAllocateBusNumber (PciDevice, SecondBus, (UINT= 8) > (BusRange), &PaddedSubBus); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + *SubBusNumber =3D MAX (PaddedSubBus, *SubBusNumber); > + } > + } > + > + // > + // Set the current maximum bus number under the PPB > + // > + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, > PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); > + > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint8, > + Address, > + 1, > + SubBusNumber > + ); > + } else { > + // > + // It is device. Check PCI IOV for Bus reservation > + // Go through each function, just reserve the MAX ReservedBusNum > for one device > + // > + if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOf= fset > !=3D 0) { > + if (TempReservedBusNum < PciDevice->ReservedBusNum) { > + > + Status =3D PciAllocateBusNumber (PciDevice, *SubBusNumber, (= UINT8) > (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + TempReservedBusNum =3D PciDevice->ReservedBusNum; > + > + if (Func =3D=3D 0) { > + DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x= \n", > *SubBusNumber)); > + } else { > + DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x > (Update)\n", *SubBusNumber)); > + } > + } > + } > + } > + > + if (Func =3D=3D 0 && !IS_PCI_MULTI_FUNC (&Pci)) { > + > + // > + // Skip sub functions, this is not a multi function device > + // > + > + Func =3D PCI_MAX_FUNC; > + } > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Process Option Rom on the specified root bridge. > + > + @param Bridge Pci root bridge device instance. > + > + @retval EFI_SUCCESS Success process. > + @retval other Some error occurred when processing Option Rom o= n > the root bridge. > + > +**/ > +EFI_STATUS > +PciRootBridgeP2CProcess ( > + IN PCI_IO_DEVICE *Bridge > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_IO_DEVICE *Temp; > + EFI_HPC_STATE State; > + UINT64 PciAddress; > + EFI_STATUS Status; > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + if (IS_CARDBUS_BRIDGE (&Temp->Pci)) { > + > + if (gPciHotPlugInit !=3D NULL && Temp->Allocated && FeaturePcdGet > (PcdPciBusHotplugDeviceSupport)) { > + > + // > + // Raise the EFI_IOB_PCI_HPC_INIT status code > + // > + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( > + EFI_PROGRESS_CODE, > + EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT, > + Temp->DevicePath > + ); > + > + PciAddress =3D EFI_PCI_ADDRESS (Temp->BusNumber, Temp- > >DeviceNumber, Temp->FunctionNumber, 0); > + Status =3D gPciHotPlugInit->InitializeRootHpc ( > + gPciHotPlugInit, > + Temp->DevicePath, > + PciAddress, > + NULL, > + &State > + ); > + > + if (!EFI_ERROR (Status)) { > + Status =3D PciBridgeEnumerator (Temp); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + continue; > + > + } > + } > + > + if (!IsListEmpty (&Temp->ChildList)) { > + Status =3D PciRootBridgeP2CProcess (Temp); > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Process Option Rom on the specified host bridge. > + > + @param PciResAlloc Pointer to instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + > + @retval EFI_SUCCESS Success process. > + @retval EFI_NOT_FOUND Can not find the root bridge instance. > + @retval other Some error occurred when processing Option Rom o= n > the host bridge. > + > +**/ > +EFI_STATUS > +PciHostBridgeP2CProcess ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ) > +{ > + EFI_HANDLE RootBridgeHandle; > + PCI_IO_DEVICE *RootBridgeDev; > + EFI_STATUS Status; > + > + if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + return EFI_SUCCESS; > + } > + > + RootBridgeHandle =3D NULL; > + > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) > =3D=3D EFI_SUCCESS) { > + > + // > + // Get RootBridg Device by handle > + // > + RootBridgeDev =3D GetRootBridgeByHandle (RootBridgeHandle); > + > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + Status =3D PciRootBridgeP2CProcess (RootBridgeDev); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is used to enumerate the entire host bridge > + in a given platform. > + > + @param PciResAlloc A pointer to the PCI Host Resource Allocation > protocol. > + > + @retval EFI_SUCCESS Successfully enumerated the host bridge= . > + @retval EFI_OUT_OF_RESOURCES No enough memory available. > + @retval other Some error occurred when enumerating th= e host > bridge. > + > +**/ > +EFI_STATUS > +PciHostBridgeEnumerator ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ) > +{ > + EFI_HANDLE RootBridgeHandle; > + PCI_IO_DEVICE *RootBridgeDev; > + EFI_STATUS Status; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + UINT16 MinBus; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration; > + UINT8 StartBusNumber; > + LIST_ENTRY RootBridgeList; > + LIST_ENTRY *Link; > + > + if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { > + InitializeHotPlugSupport (); > + } > + > + InitializeListHead (&RootBridgeList); > + > + // > + // Notify the bus allocation phase is about to start > + // > + Status =3D NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocatio= n); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n")); > + RootBridgeHandle =3D NULL; > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) > =3D=3D EFI_SUCCESS) { > + > + // > + // if a root bridge instance is found, create root bridge device for= it > + // > + > + RootBridgeDev =3D CreateRootBridge (RootBridgeHandle); > + > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Enumerate all the buses under this root bridge > + // > + Status =3D PciRootBridgeEnumerator ( > + PciResAlloc, > + RootBridgeDev > + ); > + > + if (gPciHotPlugInit !=3D NULL && FeaturePcdGet > (PcdPciBusHotplugDeviceSupport)) { > + InsertTailList (&RootBridgeList, &(RootBridgeDev->Link)); > + } else { > + DestroyRootBridge (RootBridgeDev); > + } > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + // > + // Notify the bus allocation phase is finished for the first time > + // > + NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation); > + > + if (gPciHotPlugInit !=3D NULL && FeaturePcdGet > (PcdPciBusHotplugDeviceSupport)) { > + // > + // Reset all assigned PCI bus number in all PPB > + // > + RootBridgeHandle =3D NULL; > + Link =3D GetFirstNode (&RootBridgeList); > + while ((PciResAlloc->GetNextRootBridge (PciResAlloc, > &RootBridgeHandle) =3D=3D EFI_SUCCESS) && > + (!IsNull (&RootBridgeList, Link))) { > + RootBridgeDev =3D PCI_IO_DEVICE_FROM_LINK (Link); > + // > + // Get the Bus information > + // > + Status =3D PciResAlloc->StartBusEnumeration ( > + PciResAlloc, > + RootBridgeHandle, > + (VOID **) &Configuration > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Get the bus number to start with > + // > + StartBusNumber =3D (UINT8) (Configuration->AddrRangeMin); > + > + ResetAllPpbBusNumber ( > + RootBridgeDev, > + StartBusNumber > + ); > + > + FreePool (Configuration); > + Link =3D RemoveEntryList (Link); > + DestroyRootBridge (RootBridgeDev); > + } > + > + // > + // Wait for all HPC initialized > + // > + Status =3D AllRootHPCInitialized (STALL_1_SECOND * 15); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n")); > + return Status; > + } > + > + // > + // Notify the bus allocation phase is about to start for the 2nd tim= e > + // > + Status =3D NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocat= ion); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n")); > + RootBridgeHandle =3D NULL; > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, > &RootBridgeHandle) =3D=3D EFI_SUCCESS) { > + > + // > + // if a root bridge instance is found, create root bridge device f= or it > + // > + RootBridgeDev =3D CreateRootBridge (RootBridgeHandle); > + > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Enumerate all the buses under this root bridge > + // > + Status =3D PciRootBridgeEnumerator ( > + PciResAlloc, > + RootBridgeDev > + ); > + > + DestroyRootBridge (RootBridgeDev); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + // > + // Notify the bus allocation phase is to end for the 2nd time > + // > + NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation); > + } > + > + // > + // Notify the resource allocation phase is to start > + // > + Status =3D NotifyPhase (PciResAlloc, > EfiPciHostBridgeBeginResourceAllocation); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + RootBridgeHandle =3D NULL; > + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) > =3D=3D EFI_SUCCESS) { > + > + // > + // if a root bridge instance is found, create root bridge device for= it > + // > + RootBridgeDev =3D CreateRootBridge (RootBridgeHandle); > + > + if (RootBridgeDev =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status =3D StartManagingRootBridge (RootBridgeDev); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + PciRootBridgeIo =3D RootBridgeDev->PciRootBridgeIo; > + Status =3D PciRootBridgeIo->Configuration (PciRootBridgeIo,= (VOID **) > &Descriptors); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D PciGetBusRange (&Descriptors, &MinBus, NULL, NULL); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Determine root bridge attribute by calling interface of Pcihostbr= idge > + // protocol > + // > + DetermineRootBridgeAttributes ( > + PciResAlloc, > + RootBridgeDev > + ); > + > + // > + // Collect all the resource information under this root bridge > + // A database that records all the information about pci device subj= ect to > this > + // root bridge will then be created > + // > + Status =3D PciPciDeviceInfoCollector ( > + RootBridgeDev, > + (UINT8) MinBus > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + InsertRootBridge (RootBridgeDev); > + > + // > + // Record the hostbridge handle > + // > + AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo- > >ParentHandle); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + This function is used to program the Resizable BAR Register. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param ResizableBarOp PciResizableBarMax: Set BAR to max size > + PciResizableBarMin: set BAR to min size. > + > + @retval EFI_SUCCESS Successfully enumerated the host bridge. > + @retval other Some error occurred when enumerating the= host > bridge. > + > +**/ > +EFI_STATUS > +PciProgramResizableBar ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT64 Capabilities; > + UINT32 Index; > + UINT32 Offset; > + INTN Bit; > + UINTN ResizableBarNumber; > + EFI_STATUS Status; > + PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY > Entries[PCI_MAX_BAR]; > + > + ASSERT (PciIoDevice->ResizableBarOffset !=3D 0); > + > + DEBUG ((DEBUG_INFO, " Programs Resizable BAR register, offset: > 0x%08x, number: %d\n", > + PciIoDevice->ResizableBarOffset, PciIoDevice->ResizableBarNumber= )); > + > + ResizableBarNumber =3D MIN (PciIoDevice->ResizableBarNumber, > PCI_MAX_BAR); > + PciIo =3D &PciIoDevice->PciIo; > + Status =3D PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint8, > + PciIoDevice->ResizableBarOffset + sizeof > (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER), > + sizeof > (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * > ResizableBarNumber, > + (VOID *)(&Entries) > + ); > + ASSERT_EFI_ERROR (Status); > + > + for (Index =3D 0; Index < ResizableBarNumber; Index++) { > + > + // > + // When the bit of Capabilities Set, indicates that the Function sup= ports > + // operating with the BAR sized to (2^Bit) MB. > + // Example: > + // Bit 0 is set: supports operating with the BAR sized to 1 MB > + // Bit 1 is set: supports operating with the BAR sized to 2 MB > + // Bit n is set: supports operating with the BAR sized to (2^n) MB > + // > + Capabilities =3D > LShiftU64(Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28) > + | Entries[Index].ResizableBarCapability.Bits.BarSizeCa= pability; > + > + if (ResizableBarOp =3D=3D PciResizableBarMax) { > + Bit =3D HighBitSet64(Capabilities); > + } else { > + ASSERT (ResizableBarOp =3D=3D PciResizableBarMin); > + Bit =3D LowBitSet64(Capabilities); > + } > + > + ASSERT (Bit >=3D 0); > + > + Offset =3D PciIoDevice->ResizableBarOffset + sizeof > (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER) > + + Index * sizeof > (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) > + + OFFSET_OF > (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, > ResizableBarControl); > + > + Entries[Index].ResizableBarControl.Bits.BarSize =3D (UINT32) Bit; > + DEBUG (( > + DEBUG_INFO, > + " Resizable Bar: Offset =3D 0x%x, Bar Size Capability =3D 0x%016= lx, New Bar > Size =3D 0x%lx\n", > + OFFSET_OF (PCI_TYPE00, > Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]), > + Capabilities, LShiftU64 (SIZE_1MB, Bit) > + )); > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + Offset, > + 1, > + &Entries[Index].ResizableBarControl.Uint32 > + ); > + } > + > + return EFI_SUCCESS; > +} > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciLib.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciLib.h > new file mode 100644 > index 0000000000..70ab07a8c3 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciLib.h > @@ -0,0 +1,179 @@ > +/** @file > + Internal library declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_LIB_H_ > +#define _EFI_PCI_LIB_H_ > + > + > +typedef struct { > + EFI_HANDLE Handle; > +} EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD; > + > +typedef struct { > + UINT32 Bar; > + UINT16 DevicePathSize; > + UINT16 ReqResSize; > + UINT16 AllocResSize; > + UINT8 *DevicePath; > + UINT8 *ReqRes; > + UINT8 *AllocRes; > +} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD; > + > +typedef enum { > + PciResizableBarMin =3D 0x00, > + PciResizableBarMax =3D 0xFF > +} PCI_RESIZABLE_BAR_OPERATION; > + > +/** > + Retrieve the PCI Card device BAR information via PciIo interface. > + > + @param PciIoDevice PCI Card device instance. > + > +**/ > +VOID > +GetBackPcCardBar ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Remove rejected pci device from specific root bridge > + handle. > + > + @param RootBridgeHandle Specific parent root bridge handle. > + @param Bridge Bridge device instance. > + > +**/ > +VOID > +RemoveRejectedPciDevices ( > + IN EFI_HANDLE RootBridgeHandle, > + IN PCI_IO_DEVICE *Bridge > + ); > + > +/** > + Submits the I/O and memory resource requirements for the specified PCI > Host Bridge. > + > + @param PciResAlloc Point to protocol instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + > + @retval EFI_SUCCESS Successfully finished resource allocatio= n. > + @retval EFI_NOT_FOUND Cannot get root bridge instance. > + @retval EFI_OUT_OF_RESOURCES Platform failed to program the > resources if no hot plug supported. > + @retval other Some error occurred when allocating reso= urces for > the PCI Host Bridge. > + > + @note Feature flag PcdPciBusHotplugDeviceSupport determine whether > need support hotplug. > + > +**/ > +EFI_STATUS > +PciHostBridgeResourceAllocator ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ); > + > +/** > + Allocate NumberOfBuses buses and return the next available PCI bus > number. > + > + @param Bridge Bridge device instance. > + @param StartBusNumber Current available PCI bus number. > + @param NumberOfBuses Number of buses enumerated below the > StartBusNumber. > + @param NextBusNumber Next available PCI bus number. > + > + @retval EFI_SUCCESS Available bus number resource is enough.= Next > available PCI bus number > + is returned in NextBusNumber. > + @retval EFI_OUT_OF_RESOURCES Available bus number resource is not > enough for allocation. > + > +**/ > +EFI_STATUS > +PciAllocateBusNumber ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber, > + IN UINT8 NumberOfBuses, > + OUT UINT8 *NextBusNumber > + ); > + > +/** > + Scan pci bus and assign bus number to the given PCI bus system. > + > + @param Bridge Bridge device instance. > + @param StartBusNumber start point. > + @param SubBusNumber Point to sub bus number. > + @param PaddedBusRange Customized bus number. > + > + @retval EFI_SUCCESS Successfully scanned and assigned bus number. > + @retval other Some error occurred when scanning pci bus. > + > + @note Feature flag PcdPciBusHotplugDeviceSupport determine whether > need support hotplug. > + > +**/ > +EFI_STATUS > +PciScanBus ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT8 StartBusNumber, > + OUT UINT8 *SubBusNumber, > + OUT UINT8 *PaddedBusRange > + ); > + > +/** > + Process Option Rom on the specified root bridge. > + > + @param Bridge Pci root bridge device instance. > + > + @retval EFI_SUCCESS Success process. > + @retval other Some error occurred when processing Option Rom o= n > the root bridge. > + > +**/ > +EFI_STATUS > +PciRootBridgeP2CProcess ( > + IN PCI_IO_DEVICE *Bridge > + ); > + > +/** > + Process Option Rom on the specified host bridge. > + > + @param PciResAlloc Pointer to instance of > EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. > + > + @retval EFI_SUCCESS Success process. > + @retval EFI_NOT_FOUND Can not find the root bridge instance. > + @retval other Some error occurred when processing Option Rom o= n > the host bridge. > + > +**/ > +EFI_STATUS > +PciHostBridgeP2CProcess ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ); > + > +/** > + This function is used to enumerate the entire host bridge > + in a given platform. > + > + @param PciResAlloc A pointer to the PCI Host Resource Allocation > protocol. > + > + @retval EFI_SUCCESS Successfully enumerated the host bridge= . > + @retval EFI_OUT_OF_RESOURCES No enough memory available. > + @retval other Some error occurred when enumerating th= e host > bridge. > + > +**/ > +EFI_STATUS > +PciHostBridgeEnumerator ( > + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL > *PciResAlloc > + ); > + > +/** > + This function is used to program the Resizable BAR Register. > + > + @param PciIoDevice A pointer to the PCI_IO_DEVICE. > + @param ResizableBarOp PciResizableBarMax: Set BAR to max size > + PciResizableBarMin: set BAR to min size. > + > + @retval EFI_SUCCESS Successfully enumerated the host bridge. > + @retval other Some error occurred when enumerating the= host > bridge. > + > +**/ > +EFI_STATUS > +PciProgramResizableBar ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp > + ); > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciOptionRomSupport.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciOptionRomSupport.c > new file mode 100644 > index 0000000000..efdfa2d415 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciOptionRomSupport.c > @@ -0,0 +1,776 @@ > +/** @file > + PCI Rom supporting funtions implementation for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2021, American Megatrends International LLC.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +/** > + Load the EFI Image from Option ROM > + > + @param PciIoDevice PCI IO device instance. > + @param FilePath The file path of the EFI Image > + @param BufferSize On input the size of Buffer in bytes. On output w= ith a > return > + code of EFI_SUCCESS, the amount of data transferr= ed to Buffer. > + On output with a return code of EFI_BUFFER_TOO_SM= ALL, > + the size of Buffer required to retrieve the reque= sted file. > + @param Buffer The memory buffer to transfer the file to. If Buf= fer is > NULL, > + then no the size of the requested file is returne= d in BufferSize. > + > + @retval EFI_SUCCESS The file was loaded. > + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or > + BufferSize is NULL. > + @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device. > + @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom > image. > + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the > current directory entry. > + BufferSize has been updated with the siz= e needed to > complete the request. > +**/ > +EFI_STATUS > +LocalLoadFile2 ( > + IN PCI_IO_DEVICE *PciIoDevice, > + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, > + IN OUT UINTN *BufferSize, > + IN VOID *Buffer OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH > *EfiOpRomImageNode; > + EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; > + PCI_DATA_STRUCTURE *Pcir; > + UINT32 ImageSize; > + UINT8 *ImageBuffer; > + UINT32 ImageLength; > + UINT32 DestinationSize; > + UINT32 ScratchSize; > + VOID *Scratch; > + EFI_DECOMPRESS_PROTOCOL *Decompress; > + UINT32 InitializationSize; > + > + EfiOpRomImageNode =3D > (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath; > + if ((EfiOpRomImageNode =3D=3D NULL) || > + (DevicePathType (FilePath) !=3D MEDIA_DEVICE_PATH) || > + (DevicePathSubType (FilePath) !=3D > MEDIA_RELATIVE_OFFSET_RANGE_DP) || > + (DevicePathNodeLength (FilePath) !=3D sizeof > (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) || > + (!IsDevicePathEnd (NextDevicePathNode (FilePath))) || > + (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode- > >EndingOffset) || > + (EfiOpRomImageNode->EndingOffset >=3D PciIoDevice->RomSize) || > + (BufferSize =3D=3D NULL) > + ) { > + return EFI_INVALID_PARAMETER; > + } > + > + EfiRomHeader =3D (EFI_PCI_EXPANSION_ROM_HEADER *) ( > + (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode- > >StartingOffset > + ); > + if (EfiRomHeader->Signature !=3D > PCI_EXPANSION_ROM_HEADER_SIGNATURE) { > + return EFI_NOT_FOUND; > + } > + > + > + Pcir =3D (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + > EfiRomHeader->PcirOffset); > + ASSERT (Pcir->Signature =3D=3D PCI_DATA_STRUCTURE_SIGNATURE); > + > + if ((Pcir->CodeType =3D=3D PCI_CODE_TYPE_EFI_IMAGE) && > + (EfiRomHeader->EfiSignature =3D=3D > EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) && > + ((EfiRomHeader->EfiSubsystem =3D=3D > EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || > + (EfiRomHeader->EfiSubsystem =3D=3D > EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) && > + (EfiRomHeader->CompressionType <=3D > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) > + ) { > + > + ImageSize =3D Pcir->ImageLength * 512; > + InitializationSize =3D (UINT32) EfiRomHeader->InitializationSize * 5= 12; > + if (InitializationSize > ImageSize || EfiRomHeader->EfiImageHeaderOf= fset > >=3D InitializationSize) { > + return EFI_NOT_FOUND; > + } > + > + ImageBuffer =3D (UINT8 *) EfiRomHeader + EfiRomHeader- > >EfiImageHeaderOffset; > + ImageLength =3D InitializationSize - EfiRomHeader- > >EfiImageHeaderOffset; > + > + if (EfiRomHeader->CompressionType !=3D > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { > + // > + // Uncompressed: Copy the EFI Image directly to user's buffer > + // > + if (Buffer =3D=3D NULL || *BufferSize < ImageLength) { > + *BufferSize =3D ImageLength; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + *BufferSize =3D ImageLength; > + CopyMem (Buffer, ImageBuffer, ImageLength); > + return EFI_SUCCESS; > + > + } else { > + // > + // Compressed: Uncompress before copying > + // > + Status =3D gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, > (VOID **) &Decompress); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + Status =3D Decompress->GetInfo ( > + Decompress, > + ImageBuffer, > + ImageLength, > + &DestinationSize, > + &ScratchSize > + ); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + > + if (Buffer =3D=3D NULL || *BufferSize < DestinationSize) { > + *BufferSize =3D DestinationSize; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + *BufferSize =3D DestinationSize; > + Scratch =3D AllocatePool (ScratchSize); > + if (Scratch =3D=3D NULL) { > + return EFI_DEVICE_ERROR; > + } > + > + Status =3D Decompress->Decompress ( > + Decompress, > + ImageBuffer, > + ImageLength, > + Buffer, > + DestinationSize, > + Scratch, > + ScratchSize > + ); > + FreePool (Scratch); > + > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + return EFI_SUCCESS; > + } > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + Initialize a PCI LoadFile2 instance. > + > + @param PciIoDevice PCI IO Device. > + > +**/ > +VOID > +InitializePciLoadFile2 ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + PciIoDevice->LoadFile2.LoadFile =3D LoadFile2; > +} > + > +/** > + Causes the driver to load a specified file. > + > + @param This Indicates a pointer to the calling context. > + @param FilePath The device specific path of the file to load. > + @param BootPolicy Should always be FALSE. > + @param BufferSize On input the size of Buffer in bytes. On output wit= h a > return > + code of EFI_SUCCESS, the amount of data transferred= to Buffer. > + On output with a return code of EFI_BUFFER_TOO_SMAL= L, > + the size of Buffer required to retrieve the request= ed file. > + @param Buffer The memory buffer to transfer the file to. If Buffe= r is > NULL, > + then no the size of the requested file is returned = in BufferSize. > + > + @retval EFI_SUCCESS The file was loaded. > + @retval EFI_UNSUPPORTED BootPolicy is TRUE. > + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or > + BufferSize is NULL. > + @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device. > + @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom > image. > + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the > current directory entry. > + BufferSize has been updated with the siz= e needed to > complete the request. > + > +**/ > +EFI_STATUS > +EFIAPI > +LoadFile2 ( > + IN EFI_LOAD_FILE2_PROTOCOL *This, > + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, > + IN BOOLEAN BootPolicy, > + IN OUT UINTN *BufferSize, > + IN VOID *Buffer OPTIONAL > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + > + if (BootPolicy) { > + return EFI_UNSUPPORTED; > + } > + PciIoDevice =3D PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This); > + > + return LocalLoadFile2 ( > + PciIoDevice, > + FilePath, > + BufferSize, > + Buffer > + ); > +} > + > +/** > + Get Pci device's oprom information. > + > + @param PciIoDevice Input Pci device instance. > + Output Pci device instance with updated OptionRo= m size. > + > + @retval EFI_NOT_FOUND Pci device has not Option Rom. > + @retval EFI_SUCCESS Pci device has Option Rom. > + > +**/ > +EFI_STATUS > +GetOpRomInfo ( > + IN OUT PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + UINT8 RomBarIndex; > + UINT32 AllOnes; > + UINT64 Address; > + EFI_STATUS Status; > + UINT8 Bus; > + UINT8 Device; > + UINT8 Function; > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + > + Bus =3D PciIoDevice->BusNumber; > + Device =3D PciIoDevice->DeviceNumber; > + Function =3D PciIoDevice->FunctionNumber; > + > + PciRootBridgeIo =3D PciIoDevice->PciRootBridgeIo; > + > + // > + // Offset is 0x30 if is not ppb > + // > + > + // > + // 0x30 > + // > + RomBarIndex =3D PCI_EXPANSION_ROM_BASE; > + > + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { > + // > + // If is ppb, 0x38 > + // > + RomBarIndex =3D PCI_BRIDGE_ROMBAR; > + } > + // > + // The bit0 is 0 to prevent the enabling of the Rom address decoder > + // > + AllOnes =3D 0xfffffffe; > + Address =3D EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex); > + > + Status =3D PciRootBridgeIo->Pci.Write ( > + PciRootBridgeIo, > + EfiPciWidthUint32, > + Address, > + 1, > + &AllOnes > + ); > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Read back > + // > + Status =3D PciRootBridgeIo->Pci.Read( > + PciRootBridgeIo, > + EfiPciWidthUint32, > + Address, > + 1, > + &AllOnes > + ); > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Bits [1, 10] are reserved > + // > + AllOnes &=3D 0xFFFFF800; > + if ((AllOnes =3D=3D 0) || (AllOnes =3D=3D 0xFFFFF800)) { > + return EFI_NOT_FOUND; > + } > + > + PciIoDevice->RomSize =3D (~AllOnes) + 1; > + return EFI_SUCCESS; > +} > + > +/** > + Check if the RomImage contains EFI Images. > + > + @param RomImage The ROM address of Image for check. > + @param RomSize Size of ROM for check. > + > + @retval TRUE ROM contain EFI Image. > + @retval FALSE ROM not contain EFI Image. > + > +**/ > +BOOLEAN > +ContainEfiImage ( > + IN VOID *RomImage, > + IN UINT64 RomSize > + ) > +{ > + PCI_EXPANSION_ROM_HEADER *RomHeader; > + PCI_DATA_STRUCTURE *RomPcir; > + UINT8 Indicator; > + > + Indicator =3D 0; > + RomHeader =3D RomImage; > + if (RomHeader =3D=3D NULL) { > + return FALSE; > + } > + > + do { > + if (RomHeader->Signature !=3D > PCI_EXPANSION_ROM_HEADER_SIGNATURE) { > + RomHeader =3D (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) > RomHeader + 512); > + continue; > + } > + > + // > + // The PCI Data Structure must be DWORD aligned. > + // > + if (RomHeader->PcirOffset =3D=3D 0 || > + (RomHeader->PcirOffset & 3) !=3D 0 || > + (UINT8 *) RomHeader + RomHeader->PcirOffset + sizeof > (PCI_DATA_STRUCTURE) > (UINT8 *) RomImage + RomSize) { > + break; > + } > + > + RomPcir =3D (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + > RomHeader->PcirOffset); > + if (RomPcir->Signature !=3D PCI_DATA_STRUCTURE_SIGNATURE) { > + break; > + } > + > + if (RomPcir->CodeType =3D=3D PCI_CODE_TYPE_EFI_IMAGE) { > + return TRUE; > + } > + > + Indicator =3D RomPcir->Indicator; > + RomHeader =3D (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader > + RomPcir->ImageLength * 512); > + } while (((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) && > ((Indicator & 0x80) =3D=3D 0x00)); > + > + return FALSE; > +} > + > +/** > + Load Option Rom image for specified PCI device. > + > + @param PciDevice Pci device instance. > + @param RomBase Base address of Option Rom. > + > + @retval EFI_OUT_OF_RESOURCES No enough memory to hold image. > + @retval EFI_SUCESS Successfully loaded Option Rom. > + > +**/ > +EFI_STATUS > +LoadOpRomImage ( > + IN PCI_IO_DEVICE *PciDevice, > + IN UINT64 RomBase > + ) > +{ > + UINT8 RomBarIndex; > + UINT8 Indicator; > + UINT16 OffsetPcir; > + UINT32 RomBarOffset; > + UINT32 RomBar; > + EFI_STATUS RetStatus; > + BOOLEAN FirstCheck; > + UINT8 *Image; > + PCI_EXPANSION_ROM_HEADER *RomHeader; > + PCI_DATA_STRUCTURE *RomPcir; > + UINT64 RomSize; > + UINT64 RomImageSize; > + UINT32 LegacyImageLength; > + UINT8 *RomInMemory; > + UINT8 CodeType; > + > + RomSize =3D PciDevice->RomSize; > + > + Indicator =3D 0; > + RomImageSize =3D 0; > + RomInMemory =3D NULL; > + CodeType =3D 0xFF; > + > + // > + // Get the RomBarIndex > + // > + > + // > + // 0x30 > + // > + RomBarIndex =3D PCI_EXPANSION_ROM_BASE; > + if (IS_PCI_BRIDGE (&(PciDevice->Pci))) { > + // > + // if is ppb > + // > + > + // > + // 0x38 > + // > + RomBarIndex =3D PCI_BRIDGE_ROMBAR; > + } > + // > + // Allocate memory for Rom header and PCIR > + // > + RomHeader =3D AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER)); > + if (RomHeader =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + RomPcir =3D AllocatePool (sizeof (PCI_DATA_STRUCTURE)); > + if (RomPcir =3D=3D NULL) { > + FreePool (RomHeader); > + return EFI_OUT_OF_RESOURCES; > + } > + > + RomBar =3D (UINT32) RomBase; > + > + // > + // Enable RomBar > + // > + RomDecode (PciDevice, RomBarIndex, RomBar, TRUE); > + > + RomBarOffset =3D RomBar; > + RetStatus =3D EFI_NOT_FOUND; > + FirstCheck =3D TRUE; > + LegacyImageLength =3D 0; > + > + do { > + PciDevice->PciRootBridgeIo->Mem.Read ( > + PciDevice->PciRootBridgeIo, > + EfiPciWidthUint8, > + RomBarOffset, > + sizeof (PCI_EXPANSION_ROM_HEADER), > + (UINT8 *) RomHeader > + ); > + > + if (RomHeader->Signature !=3D > PCI_EXPANSION_ROM_HEADER_SIGNATURE) { > + RomBarOffset =3D RomBarOffset + 512; > + if (FirstCheck) { > + break; > + } else { > + RomImageSize =3D RomImageSize + 512; > + continue; > + } > + } > + > + FirstCheck =3D FALSE; > + OffsetPcir =3D RomHeader->PcirOffset; > + // > + // If the pointer to the PCI Data Structure is invalid, no further i= mages can > be located. > + // The PCI Data Structure must be DWORD aligned. > + // > + if (OffsetPcir =3D=3D 0 || > + (OffsetPcir & 3) !=3D 0 || > + RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > > RomSize) { > + break; > + } > + PciDevice->PciRootBridgeIo->Mem.Read ( > + PciDevice->PciRootBridgeIo, > + EfiPciWidthUint8, > + RomBarOffset + OffsetPcir, > + sizeof (PCI_DATA_STRUCTURE), > + (UINT8 *) RomPcir > + ); > + // > + // If a valid signature is not present in the PCI Data Structure, no= further > images can be located. > + // > + if (RomPcir->Signature !=3D PCI_DATA_STRUCTURE_SIGNATURE) { > + break; > + } > + if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) { > + break; > + } > + if (RomPcir->CodeType =3D=3D PCI_CODE_TYPE_PCAT_IMAGE) { > + CodeType =3D PCI_CODE_TYPE_PCAT_IMAGE; > + LegacyImageLength =3D > ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)- > >Size512) * 512; > + } > + Indicator =3D RomPcir->Indicator; > + RomImageSize =3D RomImageSize + RomPcir->ImageLength * 512; > + RomBarOffset =3D RomBarOffset + RomPcir->ImageLength * 512; > + } while (((Indicator & 0x80) =3D=3D 0x00) && ((RomBarOffset - RomBar) = < > RomSize)); > + > + // > + // Some Legacy Cards do not report the correct ImageLength so used the > maximum > + // of the legacy length and the PCIR Image Length > + // > + if (CodeType =3D=3D PCI_CODE_TYPE_PCAT_IMAGE) { > + RomImageSize =3D MAX (RomImageSize, LegacyImageLength); > + } > + > + if (RomImageSize > 0) { > + RetStatus =3D EFI_SUCCESS; > + Image =3D AllocatePool ((UINT32) RomImageSize); > + if (Image =3D=3D NULL) { > + RomDecode (PciDevice, RomBarIndex, RomBar, FALSE); > + FreePool (RomHeader); > + FreePool (RomPcir); > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Copy Rom image into memory > + // > + PciDevice->PciRootBridgeIo->Mem.Read ( > + PciDevice->PciRootBridgeIo, > + EfiPciWidthUint8, > + RomBar, > + (UINT32) RomImageSize, > + Image > + ); > + RomInMemory =3D Image; > + } > + > + RomDecode (PciDevice, RomBarIndex, RomBar, FALSE); > + > + PciDevice->EmbeddedRom =3D TRUE; > + PciDevice->PciIo.RomSize =3D RomImageSize; > + PciDevice->PciIo.RomImage =3D RomInMemory; > + > + //TiogaPass Override START : Skip OPROM - Mellanox card which has SSVI= D > 0x15B3 and SSDID 0x0031 > + if (PciDevice->Pci.Hdr.VendorId =3D=3D 0x15B3 && PciDevice->Pci.Hdr.De= viceId > =3D=3D 0x1015) { > + if (PciDevice->Pci.Device.SubsystemVendorID =3D=3D 0x15B3 && PciDevi= ce- > >Pci.Device.SubsystemID =3D=3D 0x0031) { > + PciDevice->PciIo.RomImage =3D NULL; > + PciDevice->PciIo.RomSize =3D 0; > + DEBUG((DEBUG_ERROR,"Device_MLX @ [B%X|D%X|F%X], VID=3D%X, > DID=3D%X SVID=3D%X, SVDID=3D%XOverrides ROM file @ %X size=3D%X .\n\n", > + PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice- > >FunctionNumber, > + PciDevice->Pci.Hdr.VendorId, PciDevice->Pci.Hdr.DeviceId, > PciDevice->Pci.Device.SubsystemVendorID,PciDevice- > >Pci.Device.SubsystemID,PciDevice->PciIo.RomImage, PciDevice- > >PciIo.RomSize)); > + } > + } > + //TiogaPass Override END > + > + // For OpROM read from PCI device: > + // Add the Rom Image to internal database for later PCI light enumer= ation > + // > + PciRomAddImageMapping ( > + NULL, > + PciDevice->PciRootBridgeIo->SegmentNumber, > + PciDevice->BusNumber, > + PciDevice->DeviceNumber, > + PciDevice->FunctionNumber, > + PciDevice->PciIo.RomImage, > + PciDevice->PciIo.RomSize > + ); > + > + // > + // Free allocated memory > + // > + FreePool (RomHeader); > + FreePool (RomPcir); > + > + return RetStatus; > +} > + > +/** > + Enable/Disable Option Rom decode. > + > + @param PciDevice Pci device instance. > + @param RomBarIndex The BAR index of the standard PCI Configuration > header to use as the > + base address for resource range. The legal range f= or this field is > 0..5. > + @param RomBar Base address of Option Rom. > + @param Enable Flag for enable/disable decode. > + > +**/ > +VOID > +RomDecode ( > + IN PCI_IO_DEVICE *PciDevice, > + IN UINT8 RomBarIndex, > + IN UINT32 RomBar, > + IN BOOLEAN Enable > + ) > +{ > + UINT32 Value32; > + EFI_PCI_IO_PROTOCOL *PciIo; > + > + PciIo =3D &PciDevice->PciIo; > + if (Enable) { > + > + // > + // set the Rom base address: now is hardcode > + // enable its decoder > + // > + Value32 =3D RomBar | 0x1; > + PciIo->Pci.Write ( > + PciIo, > + (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32, > + RomBarIndex, > + 1, > + &Value32 > + ); > + > + // > + // Programe all upstream bridge > + // > + ProgramUpstreamBridgeForRom (PciDevice, RomBar, TRUE); > + > + // > + // Setting the memory space bit in the function's command register > + // > + PCI_ENABLE_COMMAND_REGISTER(PciDevice, > EFI_PCI_COMMAND_MEMORY_SPACE); > + > + } else { > + > + // > + // disable command register decode to memory > + // > + PCI_DISABLE_COMMAND_REGISTER(PciDevice, > EFI_PCI_COMMAND_MEMORY_SPACE); > + > + // > + // Destroy the programmed bar in all the upstream bridge. > + // > + ProgramUpstreamBridgeForRom (PciDevice, RomBar, FALSE); > + > + // > + // disable rom decode > + // > + Value32 =3D 0xFFFFFFFE; > + PciIo->Pci.Write ( > + PciIo, > + (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32, > + RomBarIndex, > + 1, > + &Value32 > + ); > + > + } > +} > + > +/** > + Load and start the Option Rom image. > + > + @param PciDevice Pci device instance. > + > + @retval EFI_SUCCESS Successfully loaded and started PCI Option Rom > image. > + @retval EFI_NOT_FOUND Failed to process PCI Option Rom image. > + > +**/ > +EFI_STATUS > +ProcessOpRomImage ( > + IN PCI_IO_DEVICE *PciDevice > + ) > +{ > + UINT8 Indicator; > + UINT32 ImageSize; > + VOID *RomBar; > + UINT8 *RomBarOffset; > + EFI_HANDLE ImageHandle; > + EFI_STATUS Status; > + EFI_STATUS RetStatus; > + EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; > + PCI_DATA_STRUCTURE *Pcir; > + EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath; > + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EfiOpRomImageNode; > + VOID *Buffer; > + UINTN BufferSize; > + > + Indicator =3D 0; > + > + // > + // Get the Address of the Option Rom image > + // > + RomBar =3D PciDevice->PciIo.RomImage; > + RomBarOffset =3D (UINT8 *) RomBar; > + RetStatus =3D EFI_NOT_FOUND; > + > + if (RomBar =3D=3D NULL) { > + return RetStatus; > + } > + ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)- > >Signature =3D=3D PCI_EXPANSION_ROM_HEADER_SIGNATURE); > + > + do { > + EfiRomHeader =3D (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset; > + if (EfiRomHeader->Signature !=3D > PCI_EXPANSION_ROM_HEADER_SIGNATURE) { > + RomBarOffset +=3D 512; > + continue; > + } > + > + Pcir =3D (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader- > >PcirOffset); > + ASSERT (Pcir->Signature =3D=3D PCI_DATA_STRUCTURE_SIGNATURE); > + ImageSize =3D (UINT32) (Pcir->ImageLength * 512); > + Indicator =3D Pcir->Indicator; > + > + // > + // Skip the image if it is not an EFI PCI Option ROM image > + // > + if (Pcir->CodeType !=3D PCI_CODE_TYPE_EFI_IMAGE) { > + goto NextImage; > + } > + > + // > + // Ignore the EFI PCI Option ROM image if it is an EFI application > + // > + if (EfiRomHeader->EfiSubsystem =3D=3D > EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { > + goto NextImage; > + } > + > + // > + // Create Pci Option Rom Image device path header > + // > + EfiOpRomImageNode.Header.Type =3D MEDIA_DEVICE_PATH; > + EfiOpRomImageNode.Header.SubType =3D > MEDIA_RELATIVE_OFFSET_RANGE_DP; > + SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof > (EfiOpRomImageNode)); > + EfiOpRomImageNode.StartingOffset =3D (UINTN) RomBarOffset - (UINTN) > RomBar; > + EfiOpRomImageNode.EndingOffset =3D (UINTN) RomBarOffset + > ImageSize - 1 - (UINTN) RomBar; > + > + PciOptionRomImageDevicePath =3D AppendDevicePathNode (PciDevice- > >DevicePath, &EfiOpRomImageNode.Header); > + ASSERT (PciOptionRomImageDevicePath !=3D NULL); > + > + // > + // load image and start image > + // > + BufferSize =3D 0; > + Buffer =3D NULL; > + ImageHandle =3D NULL; > + > + Status =3D gBS->LoadImage ( > + FALSE, > + gPciBusDriverBinding.DriverBindingHandle, > + PciOptionRomImageDevicePath, > + Buffer, > + BufferSize, > + &ImageHandle > + ); > + if (EFI_ERROR (Status)) { > + // > + // Record the Option ROM Image device path when LoadImage fails. > + // PciOverride.GetDriver() will try to look for the Image Handle u= sing the > device path later. > + // > + AddDriver (PciDevice, NULL, PciOptionRomImageDevicePath); > + } else { > + Status =3D gBS->StartImage (ImageHandle, NULL, NULL); > + if (!EFI_ERROR (Status)) { > + // > + // Record the Option ROM Image Handle > + // > + AddDriver (PciDevice, ImageHandle, NULL); > + PciRomAddImageMapping ( > + ImageHandle, > + PciDevice->PciRootBridgeIo->SegmentNumber, > + PciDevice->BusNumber, > + PciDevice->DeviceNumber, > + PciDevice->FunctionNumber, > + PciDevice->PciIo.RomImage, > + PciDevice->PciIo.RomSize > + ); > + RetStatus =3D EFI_SUCCESS; > + } > + } > + FreePool (PciOptionRomImageDevicePath); > + > +NextImage: > + RomBarOffset +=3D ImageSize; > + > + } while (((Indicator & 0x80) =3D=3D 0x00) && (((UINTN) RomBarOffset - = (UINTN) > RomBar) < PciDevice->RomSize)); > + > + return RetStatus; > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciOptionRomSupport.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciOptionRomSupport.h > new file mode 100644 > index 0000000000..60e147a7b9 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciOptionRomSupport.h > @@ -0,0 +1,136 @@ > +/** @file > + PCI Rom supporting functions declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_OPTION_ROM_SUPPORT_H_ > +#define _EFI_PCI_OPTION_ROM_SUPPORT_H_ > + > + > +/** > + Initialize a PCI LoadFile2 instance. > + > + @param PciIoDevice PCI IO Device. > + > +**/ > +VOID > +InitializePciLoadFile2 ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Causes the driver to load a specified file. > + > + @param This Indicates a pointer to the calling context. > + @param FilePath The device specific path of the file to load. > + @param BootPolicy Should always be FALSE. > + @param BufferSize On input the size of Buffer in bytes. On output wit= h a > return > + code of EFI_SUCCESS, the amount of data transferred= to Buffer. > + On output with a return code of EFI_BUFFER_TOO_SMAL= L, > + the size of Buffer required to retrieve the request= ed file. > + @param Buffer The memory buffer to transfer the file to. If Buffe= r is > NULL, > + then no the size of the requested file is returned = in BufferSize. > + > + @retval EFI_SUCCESS The file was loaded. > + @retval EFI_UNSUPPORTED BootPolicy is TRUE. > + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or > + BufferSize is NULL. > + @retval EFI_NOT_FOUND Not found PCI Option Rom on PCI device. > + @retval EFI_DEVICE_ERROR Failed to decompress PCI Option Rom > image. > + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the > current directory entry. > + BufferSize has been updated with the siz= e needed to > complete the request. > + > +**/ > +EFI_STATUS > +EFIAPI > +LoadFile2 ( > + IN EFI_LOAD_FILE2_PROTOCOL *This, > + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, > + IN BOOLEAN BootPolicy, > + IN OUT UINTN *BufferSize, > + IN VOID *Buffer OPTIONAL > + ); > + > +/** > + Check if the RomImage contains EFI Images. > + > + @param RomImage The ROM address of Image for check. > + @param RomSize Size of ROM for check. > + > + @retval TRUE ROM contain EFI Image. > + @retval FALSE ROM not contain EFI Image. > + > +**/ > +BOOLEAN > +ContainEfiImage ( > + IN VOID *RomImage, > + IN UINT64 RomSize > + ); > + > +/** > + Get Pci device's oprom information. > + > + @param PciIoDevice Input Pci device instance. > + Output Pci device instance with updated OptionRo= m size. > + > + @retval EFI_NOT_FOUND Pci device has not Option Rom. > + @retval EFI_SUCCESS Pci device has Option Rom. > + > +**/ > +EFI_STATUS > +GetOpRomInfo ( > + IN OUT PCI_IO_DEVICE *PciIoDevice > + ); > + > +/** > + Load Option Rom image for specified PCI device. > + > + @param PciDevice Pci device instance. > + @param RomBase Base address of Option Rom. > + > + @retval EFI_OUT_OF_RESOURCES No enough memory to hold image. > + @retval EFI_SUCESS Successfully loaded Option Rom. > + > +**/ > +EFI_STATUS > +LoadOpRomImage ( > + IN PCI_IO_DEVICE *PciDevice, > + IN UINT64 RomBase > + ); > + > +/** > + Enable/Disable Option Rom decode. > + > + @param PciDevice Pci device instance. > + @param RomBarIndex The BAR index of the standard PCI Configuration > header to use as the > + base address for resource range. The legal range f= or this field is > 0..5. > + @param RomBar Base address of Option Rom. > + @param Enable Flag for enable/disable decode. > + > +**/ > +VOID > +RomDecode ( > + IN PCI_IO_DEVICE *PciDevice, > + IN UINT8 RomBarIndex, > + IN UINT32 RomBar, > + IN BOOLEAN Enable > + ); > + > +/** > + Load and start the Option Rom image. > + > + @param PciDevice Pci device instance. > + > + @retval EFI_SUCCESS Successfully loaded and started PCI Option Rom > image. > + @retval EFI_NOT_FOUND Failed to process PCI Option Rom image. > + > +**/ > +EFI_STATUS > +ProcessOpRomImage ( > + IN PCI_IO_DEVICE *PciDevice > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciPowerManagement.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciPowerManagement.c > new file mode 100644 > index 0000000000..cf3f8164cd > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciPowerManagement.c > @@ -0,0 +1,82 @@ > +/** @file > + Power management support functions implementation for PCI Bus > module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +/** > + This function is intended to turn off PWE assertion and > + put the device to D0 state if the device supports > + PCI Power Management. > + > + @param PciIoDevice PCI device instance. > + > + @retval EFI_UNSUPPORTED PCI Device does not support power > management. > + @retval EFI_SUCCESS Turned off PWE successfully. > + > +**/ > +EFI_STATUS > +ResetPowerManagementFeature ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_STATUS Status; > + UINT8 PowerManagementRegBlock; > + UINT16 PowerManagementCSR; > + > + PowerManagementRegBlock =3D 0; > + > + Status =3D LocateCapabilityRegBlock ( > + PciIoDevice, > + EFI_PCI_CAPABILITY_ID_PMI, > + &PowerManagementRegBlock, > + NULL > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Turn off the PWE assertion and put the device into D0 State > + // > + > + // > + // Read PMCSR > + // > + Status =3D PciIoDevice->PciIo.Pci.Read ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint16, > + PowerManagementRegBlock + 4, > + 1, > + &PowerManagementCSR > + ); > + > + if (!EFI_ERROR (Status)) { > + // > + // Clear PME_Status bit > + // > + PowerManagementCSR |=3D BIT15; > + // > + // Clear PME_En bit. PowerState =3D D0. > + // > + PowerManagementCSR &=3D ~(BIT8 | BIT1 | BIT0); > + > + // > + // Write PMCSR > + // > + Status =3D PciIoDevice->PciIo.Pci.Write ( > + &PciIoDevice->PciIo, > + EfiPciIoWidthUint16, > + PowerManagementRegBlock + 4, > + 1, > + &PowerManagementCSR > + ); > + } > + return Status; > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciPowerManagement.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciPowerManagement.h > new file mode 100644 > index 0000000000..44e97ec45a > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciPowerManagement.h > @@ -0,0 +1,28 @@ > +/** @file > + Power management support functions declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_POWER_MANAGEMENT_H_ > +#define _EFI_PCI_POWER_MANAGEMENT_H_ > + > +/** > + This function is intended to turn off PWE assertion and > + put the device to D0 state if the device supports > + PCI Power Management. > + > + @param PciIoDevice PCI device instance. > + > + @retval EFI_UNSUPPORTED PCI Device does not support power > management. > + @retval EFI_SUCCESS Turned off PWE successfully. > + > +**/ > +EFI_STATUS > +ResetPowerManagementFeature ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciResourceSupport.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciResourceSupport.c > new file mode 100644 > index 0000000000..1461af7d5d > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciResourceSupport.c > @@ -0,0 +1,2292 @@ > +/** @file > + PCI resources support functions implementation for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +// > +// The default policy for the PCI bus driver is NOT to reserve I/O range= s for > both ISA aliases and VGA aliases. > +// > +BOOLEAN mReserveIsaAliases =3D FALSE; > +BOOLEAN mReserveVgaAliases =3D FALSE; > +BOOLEAN mPolicyDetermined =3D FALSE; > + > +/** > + The function is used to skip VGA range. > + > + @param Start Returned start address including VGA range. > + @param Length The length of VGA range. > + > +**/ > +VOID > +SkipVGAAperture ( > + OUT UINT64 *Start, > + IN UINT64 Length > + ) > +{ > + UINT64 Original; > + UINT64 Mask; > + UINT64 StartOffset; > + UINT64 LimitOffset; > + > + ASSERT (Start !=3D NULL); > + // > + // For legacy VGA, bit 10 to bit 15 is not decoded > + // > + Mask =3D 0x3FF; > + > + Original =3D *Start; > + StartOffset =3D Original & Mask; > + LimitOffset =3D ((*Start) + Length - 1) & Mask; > + if (LimitOffset >=3D VGABASE1) { > + *Start =3D *Start - StartOffset + VGALIMIT2 + 1; > + } > +} > + > +/** > + This function is used to skip ISA aliasing aperture. > + > + @param Start Returned start address including ISA aliasing aperture= . > + @param Length The length of ISA aliasing aperture. > + > +**/ > +VOID > +SkipIsaAliasAperture ( > + OUT UINT64 *Start, > + IN UINT64 Length > + ) > +{ > + > + UINT64 Original; > + UINT64 Mask; > + UINT64 StartOffset; > + UINT64 LimitOffset; > + > + ASSERT (Start !=3D NULL); > + > + // > + // For legacy ISA, bit 10 to bit 15 is not decoded > + // > + Mask =3D 0x3FF; > + > + Original =3D *Start; > + StartOffset =3D Original & Mask; > + LimitOffset =3D ((*Start) + Length - 1) & Mask; > + > + if (LimitOffset >=3D ISABASE) { > + *Start =3D *Start - StartOffset + ISALIMIT + 1; > + } > +} > + > +/** > + This function inserts a resource node into the resource list. > + The resource list is sorted in descend order. > + > + @param Bridge PCI resource node for bridge. > + @param ResNode Resource node want to be inserted. > + > +**/ > +VOID > +InsertResourceNode ( > + IN OUT PCI_RESOURCE_NODE *Bridge, > + IN PCI_RESOURCE_NODE *ResNode > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_RESOURCE_NODE *Temp; > + UINT64 ResNodeAlignRest; > + UINT64 TempAlignRest; > + > + ASSERT (Bridge !=3D NULL); > + ASSERT (ResNode !=3D NULL); > + > + InsertHeadList (&Bridge->ChildList, &ResNode->Link); > + > + CurrentLink =3D Bridge->ChildList.ForwardLink->ForwardLink; > + while (CurrentLink !=3D &Bridge->ChildList) { > + Temp =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + > + if (ResNode->Alignment > Temp->Alignment) { > + break; > + } else if (ResNode->Alignment =3D=3D Temp->Alignment) { > + ResNodeAlignRest =3D ResNode->Length & ResNode->Alignment; > + TempAlignRest =3D Temp->Length & Temp->Alignment; > + if ((ResNodeAlignRest =3D=3D 0) || (ResNodeAlignRest >=3D TempAlig= nRest)) { > + break; > + } > + } > + > + SwapListEntries (&ResNode->Link, CurrentLink); > + > + CurrentLink =3D ResNode->Link.ForwardLink; > + } > +} > + > +/** > + This routine is used to merge two different resource trees in need of > + resource degradation. > + > + For example, if an upstream PPB doesn't support, > + prefetchable memory decoding, the PCI bus driver will choose to call t= his > function > + to merge prefetchable memory resource list into normal memory list. > + > + If the TypeMerge is TRUE, Res resource type is changed to the type of > destination resource > + type. > + If Dst is NULL or Res is NULL, ASSERT (). > + > + @param Dst Point to destination resource tree. > + @param Res Point to source resource tree. > + @param TypeMerge If the TypeMerge is TRUE, Res resource type is > changed to the type of > + destination resource type. > + > +**/ > +VOID > +MergeResourceTree ( > + IN PCI_RESOURCE_NODE *Dst, > + IN PCI_RESOURCE_NODE *Res, > + IN BOOLEAN TypeMerge > + ) > +{ > + > + LIST_ENTRY *CurrentLink; > + PCI_RESOURCE_NODE *Temp; > + > + ASSERT (Dst !=3D NULL); > + ASSERT (Res !=3D NULL); > + > + while (!IsListEmpty (&Res->ChildList)) { > + CurrentLink =3D Res->ChildList.ForwardLink; > + > + Temp =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + > + if (TypeMerge) { > + Temp->ResType =3D Dst->ResType; > + } > + > + RemoveEntryList (CurrentLink); > + InsertResourceNode (Dst, Temp); > + } > +} > + > +/** > + This function is used to calculate the IO16 aperture > + for a bridge. > + > + @param Bridge PCI resource node for bridge. > + > +**/ > +VOID > +CalculateApertureIo16 ( > + IN PCI_RESOURCE_NODE *Bridge > + ) > +{ > + EFI_STATUS Status; > + UINT64 Aperture; > + LIST_ENTRY *CurrentLink; > + PCI_RESOURCE_NODE *Node; > + UINT64 Offset; > + EFI_PCI_PLATFORM_POLICY PciPolicy; > + UINT64 PaddingAperture; > + > + if (!mPolicyDetermined) { > + // > + // Check PciPlatform policy > + // > + Status =3D EFI_NOT_FOUND; > + PciPolicy =3D 0; > + if (gPciPlatformProtocol !=3D NULL) { > + Status =3D gPciPlatformProtocol->GetPlatformPolicy ( > + gPciPlatformProtocol, > + &PciPolicy > + ); > + } > + > + if (EFI_ERROR (Status) && gPciOverrideProtocol !=3D NULL) { > + Status =3D gPciOverrideProtocol->GetPlatformPolicy ( > + gPciOverrideProtocol, > + &PciPolicy > + ); > + } > + > + if (!EFI_ERROR (Status)) { > + if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) !=3D 0) { > + mReserveIsaAliases =3D TRUE; > + } > + if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) !=3D 0) { > + mReserveVgaAliases =3D TRUE; > + } > + } > + mPolicyDetermined =3D TRUE; > + } > + > + Aperture =3D 0; > + PaddingAperture =3D 0; > + > + if (Bridge =3D=3D NULL) { > + return ; > + } > + > + // > + // Assume the bridge is aligned > + // > + for ( CurrentLink =3D GetFirstNode (&Bridge->ChildList) > + ; !IsNull (&Bridge->ChildList, CurrentLink) > + ; CurrentLink =3D GetNextNode (&Bridge->ChildList, CurrentLink) > + ) { > + > + Node =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + if (Node->ResourceUsage =3D=3D PciResUsagePadding) { > + ASSERT (PaddingAperture =3D=3D 0); > + PaddingAperture =3D Node->Length; > + continue; > + } > + // > + // Consider the aperture alignment > + // > + Offset =3D Aperture & (Node->Alignment); > + > + if (Offset !=3D 0) { > + > + Aperture =3D Aperture + (Node->Alignment + 1) - Offset; > + > + } > + > + // > + // IsaEnable and VGAEnable can not be implemented now. > + // If both of them are enabled, then the IO resource would > + // become too limited to meet the requirement of most of devices. > + // > + if (mReserveIsaAliases || mReserveVgaAliases) { > + if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE > (&(Node->PciDev->Pci))) { > + // > + // Check if there is need to support ISA/VGA decoding > + // If so, we need to avoid isa/vga aliasing range > + // > + if (mReserveIsaAliases) { > + SkipIsaAliasAperture ( > + &Aperture, > + Node->Length > + ); > + Offset =3D Aperture & (Node->Alignment); > + if (Offset !=3D 0) { > + Aperture =3D Aperture + (Node->Alignment + 1) - Offset; > + } > + } else if (mReserveVgaAliases) { > + SkipVGAAperture ( > + &Aperture, > + Node->Length > + ); > + Offset =3D Aperture & (Node->Alignment); > + if (Offset !=3D 0) { > + Aperture =3D Aperture + (Node->Alignment + 1) - Offset; > + } > + } > + } > + } > + > + Node->Offset =3D Aperture; > + > + // > + // Increment aperture by the length of node > + // > + Aperture +=3D Node->Length; > + } > + > + // > + // Adjust the aperture with the bridge's alignment > + // > + Offset =3D Aperture & (Bridge->Alignment); > + > + if (Offset !=3D 0) { > + Aperture =3D Aperture + (Bridge->Alignment + 1) - Offset; > + } > + > + Bridge->Length =3D Aperture; > + // > + // At last, adjust the bridge's alignment to the first child's alignme= nt > + // if the bridge has at least one child > + // > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + if (CurrentLink !=3D &Bridge->ChildList) { > + Node =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + if (Node->Alignment > Bridge->Alignment) { > + Bridge->Alignment =3D Node->Alignment; > + } > + } > + > + // > + // Hotplug controller needs padding resources. > + // Use the larger one between the padding resource and actual occupied > resource. > + // > + Bridge->Length =3D MAX (Bridge->Length, PaddingAperture); > +} > + > +/** > + This function is used to calculate the resource aperture > + for a given bridge device. > + > + @param Bridge PCI resource node for given bridge device. > + > +**/ > +VOID > +CalculateResourceAperture ( > + IN PCI_RESOURCE_NODE *Bridge > + ) > +{ > + UINT64 Aperture[2]; > + LIST_ENTRY *CurrentLink; > + PCI_RESOURCE_NODE *Node; > + > + if (Bridge =3D=3D NULL) { > + return ; > + } > + > + if (Bridge->ResType =3D=3D PciBarTypeIo16) { > + > + CalculateApertureIo16 (Bridge); > + return ; > + } > + > + Aperture[PciResUsageTypical] =3D 0; > + Aperture[PciResUsagePadding] =3D 0; > + // > + // Assume the bridge is aligned > + // > + for ( CurrentLink =3D GetFirstNode (&Bridge->ChildList) > + ; !IsNull (&Bridge->ChildList, CurrentLink) > + ; CurrentLink =3D GetNextNode (&Bridge->ChildList, CurrentLink) > + ) { > + Node =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + > + // > + // It's possible for a bridge to contain multiple padding resource > + // nodes due to DegradeResource(). > + // > + ASSERT ((Node->ResourceUsage =3D=3D PciResUsageTypical) || > + (Node->ResourceUsage =3D=3D PciResUsagePadding)); > + ASSERT (Node->ResourceUsage < ARRAY_SIZE (Aperture)); > + // > + // Recode current aperture as a offset > + // Apply padding resource to meet alignment requirement > + // Node offset will be used in future real allocation > + // > + Node->Offset =3D ALIGN_VALUE (Aperture[Node->ResourceUsage], Node- > >Alignment + 1); > + > + // > + // Record the total aperture. > + // > + Aperture[Node->ResourceUsage] =3D Node->Offset + Node->Length; > + } > + > + // > + // Adjust the aperture with the bridge's alignment > + // > + Aperture[PciResUsageTypical] =3D ALIGN_VALUE > (Aperture[PciResUsageTypical], Bridge->Alignment + 1); > + Aperture[PciResUsagePadding] =3D ALIGN_VALUE > (Aperture[PciResUsagePadding], Bridge->Alignment + 1); > + > + // > + // Hotplug controller needs padding resources. > + // Use the larger one between the padding resource and actual occupied > resource. > + // > + Bridge->Length =3D MAX (Aperture[PciResUsageTypical], > Aperture[PciResUsagePadding]); > + > + // > + // Adjust the bridge's alignment to the MAX (first) alignment of all c= hildren. > + // > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + if (CurrentLink !=3D &Bridge->ChildList) { > + Node =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + if (Node->Alignment > Bridge->Alignment) { > + Bridge->Alignment =3D Node->Alignment; > + } > + } > +} > + > +/** > + Get IO/Memory resource info for given PCI device. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO . > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +GetResourceFromDevice ( > + IN PCI_IO_DEVICE *PciDev, > + IN OUT PCI_RESOURCE_NODE *IoNode, > + IN OUT PCI_RESOURCE_NODE *Mem32Node, > + IN OUT PCI_RESOURCE_NODE *PMem32Node, > + IN OUT PCI_RESOURCE_NODE *Mem64Node, > + IN OUT PCI_RESOURCE_NODE *PMem64Node > + ) > +{ > + > + UINT8 Index; > + PCI_RESOURCE_NODE *Node; > + BOOLEAN ResourceRequested; > + > + Node =3D NULL; > + ResourceRequested =3D FALSE; > + > + for (Index =3D 0; Index < PCI_MAX_BAR; Index++) { > + > + switch ((PciDev->PciBar)[Index].BarType) { > + > + case PciBarTypeMem32: > + case PciBarTypeOpRom: > + > + Node =3D CreateResourceNode ( > + PciDev, > + (PciDev->PciBar)[Index].Length, > + (PciDev->PciBar)[Index].Alignment, > + Index, > + (PciDev->PciBar)[Index].BarType, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + Mem32Node, > + Node > + ); > + > + ResourceRequested =3D TRUE; > + break; > + > + case PciBarTypeMem64: > + > + Node =3D CreateResourceNode ( > + PciDev, > + (PciDev->PciBar)[Index].Length, > + (PciDev->PciBar)[Index].Alignment, > + Index, > + PciBarTypeMem64, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + Mem64Node, > + Node > + ); > + > + ResourceRequested =3D TRUE; > + break; > + > + case PciBarTypePMem64: > + > + Node =3D CreateResourceNode ( > + PciDev, > + (PciDev->PciBar)[Index].Length, > + (PciDev->PciBar)[Index].Alignment, > + Index, > + PciBarTypePMem64, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + PMem64Node, > + Node > + ); > + > + ResourceRequested =3D TRUE; > + break; > + > + case PciBarTypePMem32: > + > + Node =3D CreateResourceNode ( > + PciDev, > + (PciDev->PciBar)[Index].Length, > + (PciDev->PciBar)[Index].Alignment, > + Index, > + PciBarTypePMem32, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + PMem32Node, > + Node > + ); > + ResourceRequested =3D TRUE; > + break; > + > + case PciBarTypeIo16: > + case PciBarTypeIo32: > + > + Node =3D CreateResourceNode ( > + PciDev, > + (PciDev->PciBar)[Index].Length, > + (PciDev->PciBar)[Index].Alignment, > + Index, > + PciBarTypeIo16, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + IoNode, > + Node > + ); > + ResourceRequested =3D TRUE; > + break; > + > + case PciBarTypeUnknown: > + break; > + > + default: > + break; > + } > + } > + > + // > + // Add VF resource > + // > + for (Index =3D 0; Index < PCI_MAX_BAR; Index++) { > + > + switch ((PciDev->VfPciBar)[Index].BarType) { > + > + case PciBarTypeMem32: > + > + Node =3D CreateVfResourceNode ( > + PciDev, > + (PciDev->VfPciBar)[Index].Length, > + (PciDev->VfPciBar)[Index].Alignment, > + Index, > + PciBarTypeMem32, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + Mem32Node, > + Node > + ); > + > + break; > + > + case PciBarTypeMem64: > + > + Node =3D CreateVfResourceNode ( > + PciDev, > + (PciDev->VfPciBar)[Index].Length, > + (PciDev->VfPciBar)[Index].Alignment, > + Index, > + PciBarTypeMem64, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + Mem64Node, > + Node > + ); > + > + break; > + > + case PciBarTypePMem64: > + > + Node =3D CreateVfResourceNode ( > + PciDev, > + (PciDev->VfPciBar)[Index].Length, > + (PciDev->VfPciBar)[Index].Alignment, > + Index, > + PciBarTypePMem64, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + PMem64Node, > + Node > + ); > + > + break; > + > + case PciBarTypePMem32: > + > + Node =3D CreateVfResourceNode ( > + PciDev, > + (PciDev->VfPciBar)[Index].Length, > + (PciDev->VfPciBar)[Index].Alignment, > + Index, > + PciBarTypePMem32, > + PciResUsageTypical > + ); > + > + InsertResourceNode ( > + PMem32Node, > + Node > + ); > + break; > + > + case PciBarTypeIo16: > + case PciBarTypeIo32: > + break; > + > + case PciBarTypeUnknown: > + break; > + > + default: > + break; > + } > + } > + // If there is no resource requested from this device, > + // then we indicate this device has been allocated naturally. > + // > + if (!ResourceRequested) { > + PciDev->Allocated =3D TRUE; > + } > +} > + > +/** > + This function is used to create a resource node. > + > + @param PciDev Pci device instance. > + @param Length Length of Io/Memory resource. > + @param Alignment Alignment of resource. > + @param Bar Bar index. > + @param ResType Type of resource: IO/Memory. > + @param ResUsage Resource usage. > + > + @return PCI resource node created for given PCI device. > + NULL means PCI resource node is not created. > + > +**/ > +PCI_RESOURCE_NODE * > +CreateResourceNode ( > + IN PCI_IO_DEVICE *PciDev, > + IN UINT64 Length, > + IN UINT64 Alignment, > + IN UINT8 Bar, > + IN PCI_BAR_TYPE ResType, > + IN PCI_RESOURCE_USAGE ResUsage > + ) > +{ > + PCI_RESOURCE_NODE *Node; > + > + Node =3D NULL; > + > + Node =3D AllocateZeroPool (sizeof (PCI_RESOURCE_NODE)); > + ASSERT (Node !=3D NULL); > + if (Node =3D=3D NULL) { > + return NULL; > + } > + > + Node->Signature =3D PCI_RESOURCE_SIGNATURE; > + Node->PciDev =3D PciDev; > + Node->Length =3D Length; > + Node->Alignment =3D Alignment; > + Node->Bar =3D Bar; > + Node->ResType =3D ResType; > + Node->Reserved =3D FALSE; > + Node->ResourceUsage =3D ResUsage; > + InitializeListHead (&Node->ChildList); > + > + return Node; > +} > + > +/** > + This function is used to create a IOV VF resource node. > + > + @param PciDev Pci device instance. > + @param Length Length of Io/Memory resource. > + @param Alignment Alignment of resource. > + @param Bar Bar index. > + @param ResType Type of resource: IO/Memory. > + @param ResUsage Resource usage. > + > + @return PCI resource node created for given VF PCI device. > + NULL means PCI resource node is not created. > + > +**/ > +PCI_RESOURCE_NODE * > +CreateVfResourceNode ( > + IN PCI_IO_DEVICE *PciDev, > + IN UINT64 Length, > + IN UINT64 Alignment, > + IN UINT8 Bar, > + IN PCI_BAR_TYPE ResType, > + IN PCI_RESOURCE_USAGE ResUsage > + ) > +{ > + PCI_RESOURCE_NODE *Node; > + > + Node =3D CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, > ResUsage); > + if (Node =3D=3D NULL) { > + return Node; > + } > + > + Node->Virtual =3D TRUE; > + > + return Node; > +} > + > +/** > + This function is used to extract resource request from > + device node list. > + > + @param Bridge Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +CreateResourceMap ( > + IN PCI_IO_DEVICE *Bridge, > + IN OUT PCI_RESOURCE_NODE *IoNode, > + IN OUT PCI_RESOURCE_NODE *Mem32Node, > + IN OUT PCI_RESOURCE_NODE *PMem32Node, > + IN OUT PCI_RESOURCE_NODE *Mem64Node, > + IN OUT PCI_RESOURCE_NODE *PMem64Node > + ) > +{ > + PCI_IO_DEVICE *Temp; > + PCI_RESOURCE_NODE *IoBridge; > + PCI_RESOURCE_NODE *Mem32Bridge; > + PCI_RESOURCE_NODE *PMem32Bridge; > + PCI_RESOURCE_NODE *Mem64Bridge; > + PCI_RESOURCE_NODE *PMem64Bridge; > + LIST_ENTRY *CurrentLink; > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + while (CurrentLink !=3D NULL && CurrentLink !=3D &Bridge->ChildList) { > + > + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); > + > + // > + // Create resource nodes for this device by scanning the > + // Bar array in the device private data > + // If the upstream bridge doesn't support this device, > + // no any resource node will be created for this device > + // > + GetResourceFromDevice ( > + Temp, > + IoNode, > + Mem32Node, > + PMem32Node, > + Mem64Node, > + PMem64Node > + ); > + > + if (IS_PCI_BRIDGE (&Temp->Pci)) { > + > + // > + // If the device has children, create a bridge resource node for t= his PPB > + // Note: For PPB, memory aperture is aligned with 1MB and IO apert= ure > + // is aligned with 4KB (smaller alignments may be supported). > + // > + IoBridge =3D CreateResourceNode ( > + Temp, > + 0, > + Temp->BridgeIoAlignment, > + PPB_IO_RANGE, > + PciBarTypeIo16, > + PciResUsageTypical > + ); > + > + Mem32Bridge =3D CreateResourceNode ( > + Temp, > + 0, > + 0xFFFFF, > + PPB_MEM32_RANGE, > + PciBarTypeMem32, > + PciResUsageTypical > + ); > + > + PMem32Bridge =3D CreateResourceNode ( > + Temp, > + 0, > + 0xFFFFF, > + PPB_PMEM32_RANGE, > + PciBarTypePMem32, > + PciResUsageTypical > + ); > + > + Mem64Bridge =3D CreateResourceNode ( > + Temp, > + 0, > + 0xFFFFF, > + PPB_MEM64_RANGE, > + PciBarTypeMem64, > + PciResUsageTypical > + ); > + > + PMem64Bridge =3D CreateResourceNode ( > + Temp, > + 0, > + 0xFFFFF, > + PPB_PMEM64_RANGE, > + PciBarTypePMem64, > + PciResUsageTypical > + ); > + > + // > + // Recursively create resource map on this bridge > + // > + CreateResourceMap ( > + Temp, > + IoBridge, > + Mem32Bridge, > + PMem32Bridge, > + Mem64Bridge, > + PMem64Bridge > + ); > + > + if (ResourceRequestExisted (IoBridge)) { > + InsertResourceNode ( > + IoNode, > + IoBridge > + ); > + } else { > + FreePool (IoBridge); > + IoBridge =3D NULL; > + } > + > + // > + // If there is node under this resource bridge, > + // then calculate bridge's aperture of this type > + // and insert it into the respective resource tree. > + // If no, delete this resource bridge > + // > + if (ResourceRequestExisted (Mem32Bridge)) { > + InsertResourceNode ( > + Mem32Node, > + Mem32Bridge > + ); > + } else { > + FreePool (Mem32Bridge); > + Mem32Bridge =3D NULL; > + } > + > + // > + // If there is node under this resource bridge, > + // then calculate bridge's aperture of this type > + // and insert it into the respective resource tree. > + // If no, delete this resource bridge > + // > + if (ResourceRequestExisted (PMem32Bridge)) { > + InsertResourceNode ( > + PMem32Node, > + PMem32Bridge > + ); > + } else { > + FreePool (PMem32Bridge); > + PMem32Bridge =3D NULL; > + } > + > + // > + // If there is node under this resource bridge, > + // then calculate bridge's aperture of this type > + // and insert it into the respective resource tree. > + // If no, delete this resource bridge > + // > + if (ResourceRequestExisted (Mem64Bridge)) { > + InsertResourceNode ( > + Mem64Node, > + Mem64Bridge > + ); > + } else { > + FreePool (Mem64Bridge); > + Mem64Bridge =3D NULL; > + } > + > + // > + // If there is node under this resource bridge, > + // then calculate bridge's aperture of this type > + // and insert it into the respective resource tree. > + // If no, delete this resource bridge > + // > + if (ResourceRequestExisted (PMem64Bridge)) { > + InsertResourceNode ( > + PMem64Node, > + PMem64Bridge > + ); > + } else { > + FreePool (PMem64Bridge); > + PMem64Bridge =3D NULL; > + } > + > + } > + > + // > + // If it is P2C, apply hard coded resource padding > + // > + if (IS_CARDBUS_BRIDGE (&Temp->Pci)) { > + ResourcePaddingForCardBusBridge ( > + Temp, > + IoNode, > + Mem32Node, > + PMem32Node, > + Mem64Node, > + PMem64Node > + ); > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + // > + // To do some platform specific resource padding ... > + // > + ResourcePaddingPolicy ( > + Bridge, > + IoNode, > + Mem32Node, > + PMem32Node, > + Mem64Node, > + PMem64Node > + ); > + > + // > + // Degrade resource if necessary > + // > + DegradeResource ( > + Bridge, > + Mem32Node, > + PMem32Node, > + Mem64Node, > + PMem64Node > + ); > + > + // > + // Calculate resource aperture for this bridge device > + // > + CalculateResourceAperture (Mem32Node); > + CalculateResourceAperture (PMem32Node); > + CalculateResourceAperture (Mem64Node); > + CalculateResourceAperture (PMem64Node); > + CalculateResourceAperture (IoNode); > +} > + > +/** > + This function is used to do the resource padding for a specific platfo= rm. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +ResourcePaddingPolicy ( > + IN PCI_IO_DEVICE *PciDev, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ) > +{ > + // > + // Create padding resource node > + // > + if (PciDev->ResourcePaddingDescriptors !=3D NULL) { > + ApplyResourcePadding ( > + PciDev, > + IoNode, > + Mem32Node, > + PMem32Node, > + Mem64Node, > + PMem64Node > + ); > + } > +} > + > +/** > + This function is used to degrade resource if the upstream bridge > + doesn't support certain resource. Degradation path is > + PMEM64 -> MEM64 -> MEM32 > + PMEM64 -> PMEM32 -> MEM32 > + IO32 -> IO16. > + > + @param Bridge Pci device instance. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +DegradeResource ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ) > +{ > + PCI_IO_DEVICE *PciIoDevice; > + LIST_ENTRY *ChildDeviceLink; > + LIST_ENTRY *ChildNodeLink; > + LIST_ENTRY *NextChildNodeLink; > + PCI_RESOURCE_NODE *ResourceNode; > + > + if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) { > + // > + // If any child device has both option ROM and 64-bit BAR, degrade i= ts > PMEM64/MEM64 > + // requests in case that if a legacy option ROM image can not access= 64-bit > resources. > + // > + ChildDeviceLink =3D Bridge->ChildList.ForwardLink; > + while (ChildDeviceLink !=3D NULL && ChildDeviceLink !=3D &Bridge->Ch= ildList) > { > + PciIoDevice =3D PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink); > + if (PciIoDevice->RomSize !=3D 0) { > + if (!IsListEmpty (&Mem64Node->ChildList)) { > + ChildNodeLink =3D Mem64Node->ChildList.ForwardLink; > + while (ChildNodeLink !=3D &Mem64Node->ChildList) { > + ResourceNode =3D RESOURCE_NODE_FROM_LINK (ChildNodeLink); > + NextChildNodeLink =3D ChildNodeLink->ForwardLink; > + > + if ((ResourceNode->PciDev =3D=3D PciIoDevice) && > + (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceN= ode- > >Bar].BarTypeFixed) > + ) { > + RemoveEntryList (ChildNodeLink); > + InsertResourceNode (Mem32Node, ResourceNode); > + } > + ChildNodeLink =3D NextChildNodeLink; > + } > + } > + > + if (!IsListEmpty (&PMem64Node->ChildList)) { > + ChildNodeLink =3D PMem64Node->ChildList.ForwardLink; > + while (ChildNodeLink !=3D &PMem64Node->ChildList) { > + ResourceNode =3D RESOURCE_NODE_FROM_LINK (ChildNodeLink); > + NextChildNodeLink =3D ChildNodeLink->ForwardLink; > + > + if ((ResourceNode->PciDev =3D=3D PciIoDevice) && > + (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceN= ode- > >Bar].BarTypeFixed) > + ) { > + RemoveEntryList (ChildNodeLink); > + InsertResourceNode (PMem32Node, ResourceNode); > + } > + ChildNodeLink =3D NextChildNodeLink; > + } > + } > + > + } > + ChildDeviceLink =3D ChildDeviceLink->ForwardLink; > + } > + } > + > + // > + // If firmware is in 32-bit mode, > + // then degrade PMEM64/MEM64 requests > + // > + if (sizeof (UINTN) <=3D 4) { > + MergeResourceTree ( > + Mem32Node, > + Mem64Node, > + TRUE > + ); > + > + MergeResourceTree ( > + PMem32Node, > + PMem64Node, > + TRUE > + ); > + } else { > + // > + // if the bridge does not support MEM64, degrade MEM64 to MEM32 > + // > + if (!BridgeSupportResourceDecode (Bridge, > EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) { > + MergeResourceTree ( > + Mem32Node, > + Mem64Node, > + TRUE > + ); > + } > + > + // > + // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32 > + // > + if (!BridgeSupportResourceDecode (Bridge, > EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) { > + MergeResourceTree ( > + PMem32Node, > + PMem64Node, > + TRUE > + ); > + } > + > + // > + // if both PMEM64 and PMEM32 requests from child devices, which can > not be satisfied > + // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 > to MEM32. > + // > + if (!IsListEmpty (&PMem64Node->ChildList) && Bridge->Parent !=3D NUL= L) { > + MergeResourceTree ( > + Mem32Node, > + PMem32Node, > + TRUE > + ); > + } > + } > + > + // > + // If bridge doesn't support Pmem32 > + // degrade it to mem32 > + // > + if (!BridgeSupportResourceDecode (Bridge, > EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) { > + MergeResourceTree ( > + Mem32Node, > + PMem32Node, > + TRUE > + ); > + } > + > + // > + // if root bridge supports combined Pmem Mem decoding > + // merge these two type of resource > + // > + if (BridgeSupportResourceDecode (Bridge, > EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) { > + MergeResourceTree ( > + Mem32Node, > + PMem32Node, > + FALSE > + ); > + > + // > + // No need to check if to degrade MEM64 after merge, because > + // if there are PMEM64 still here, 64-bit decode should be supported > + // by the root bride. > + // > + MergeResourceTree ( > + Mem64Node, > + PMem64Node, > + FALSE > + ); > + } > +} > + > +/** > + Test whether bridge device support decode resource. > + > + @param Bridge Bridge device instance. > + @param Decode Decode type according to resource type. > + > + @return TRUE The bridge device support decode resource. > + @return FALSE The bridge device don't support decode resource. > + > +**/ > +BOOLEAN > +BridgeSupportResourceDecode ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT32 Decode > + ) > +{ > + if (((Bridge->Decodes) & Decode) !=3D 0) { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + This function is used to program the resource allocated > + for each resource node under specified bridge. > + > + @param Base Base address of resource to be programmed. > + @param Bridge PCI resource node for the bridge device. > + > + @retval EFI_SUCCESS Successfully to program all resources > + on given PCI bridge device. > + @retval EFI_OUT_OF_RESOURCES Base is all one. > + > +**/ > +EFI_STATUS > +ProgramResource ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Bridge > + ) > +{ > + LIST_ENTRY *CurrentLink; > + PCI_RESOURCE_NODE *Node; > + EFI_STATUS Status; > + > + if (Base =3D=3D gAllOne) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + while (CurrentLink !=3D &Bridge->ChildList) { > + > + Node =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + > + if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) { > + > + if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) { > + // > + // Program the PCI Card Bus device > + // > + ProgramP2C (Base, Node); > + } else { > + // > + // Program the PCI device BAR > + // > + ProgramBar (Base, Node); > + } > + } else { > + // > + // Program the PCI devices under this bridge > + // > + Status =3D ProgramResource (Base + Node->Offset, Node); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ProgramPpbApperture (Base, Node); > + } > + > + CurrentLink =3D CurrentLink->ForwardLink; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Program Bar register for PCI device. > + > + @param Base Base address for PCI device resource to be programmed. > + @param Node Point to resource node structure. > + > +**/ > +VOID > +ProgramBar ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT64 Address; > + UINT32 Address32; > + > + ASSERT (Node->Bar < PCI_MAX_BAR); > + > + // > + // Check VF BAR > + // > + if (Node->Virtual) { > + ProgramVfBar (Base, Node); > + return; > + } > + > + Address =3D 0; > + PciIo =3D &(Node->PciDev->PciIo); > + > + Address =3D Base + Node->Offset; > + > + // > + // Indicate pci bus driver has allocated > + // resource for this device > + // It might be a temporary solution here since > + // pci device could have multiple bar > + // > + Node->PciDev->Allocated =3D TRUE; > + > + switch ((Node->PciDev->PciBar[Node->Bar]).BarType) { > + > + case PciBarTypeIo16: > + case PciBarTypeIo32: > + case PciBarTypeMem32: > + case PciBarTypePMem32: > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (Node->PciDev->PciBar[Node->Bar]).Offset, > + 1, > + &Address > + ); > + // > + // Continue to the case PciBarTypeOpRom to set the BaseAddress. > + // PciBarTypeOpRom is a virtual BAR only in root bridge, to capture > + // the MEM32 resource requirement for Option ROM shadow. > + // > + > + case PciBarTypeOpRom: > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + > + break; > + > + case PciBarTypeMem64: > + case PciBarTypePMem64: > + > + Address32 =3D (UINT32) (Address & 0x00000000FFFFFFFF); > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (Node->PciDev->PciBar[Node->Bar]).Offset, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) RShiftU64 (Address, 32); > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4), > + 1, > + &Address32 > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + > + break; > + > + default: > + break; > + } > +} > + > +/** > + Program IOV VF Bar register for PCI device. > + > + @param Base Base address for PCI device resource to be programmed. > + @param Node Point to resource node structure. > + > +**/ > +EFI_STATUS > +ProgramVfBar ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT64 Address; > + UINT32 Address32; > + > + ASSERT (Node->Bar < PCI_MAX_BAR); > + ASSERT (Node->Virtual); > + > + Address =3D 0; > + PciIo =3D &(Node->PciDev->PciIo); > + > + Address =3D Base + Node->Offset; > + > + // > + // Indicate pci bus driver has allocated > + // resource for this device > + // It might be a temporary solution here since > + // pci device could have multiple bar > + // > + Node->PciDev->Allocated =3D TRUE; > + > + switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) { > + > + case PciBarTypeMem32: > + case PciBarTypePMem32: > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (Node->PciDev->VfPciBar[Node->Bar]).Offset, > + 1, > + &Address > + ); > + > + Node->PciDev->VfPciBar[Node->Bar].BaseAddress =3D Address; > + break; > + > + case PciBarTypeMem64: > + case PciBarTypePMem64: > + > + Address32 =3D (UINT32) (Address & 0x00000000FFFFFFFF); > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (Node->PciDev->VfPciBar[Node->Bar]).Offset, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) RShiftU64 (Address, 32); > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4), > + 1, > + &Address32 > + ); > + > + Node->PciDev->VfPciBar[Node->Bar].BaseAddress =3D Address; > + break; > + > + case PciBarTypeIo16: > + case PciBarTypeIo32: > + break; > + > + default: > + break; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Program PCI-PCI bridge aperture. > + > + @param Base Base address for resource. > + @param Node Point to resource node structure. > + > +**/ > +VOID > +ProgramPpbApperture ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT64 Address; > + UINT32 Address32; > + > + Address =3D 0; > + // > + // If no device resource of this PPB, return anyway > + // Aperture is set default in the initialization code > + // > + if (Node->Length =3D=3D 0 || Node->ResourceUsage =3D=3D PciResUsagePad= ding) > { > + // > + // For padding resource node, just ignore when programming > + // > + return ; > + } > + > + PciIo =3D &(Node->PciDev->PciIo); > + Address =3D Base + Node->Offset; > + > + // > + // Indicate the PPB resource has been allocated > + // > + Node->PciDev->Allocated =3D TRUE; > + > + switch (Node->Bar) { > + > + case PPB_BAR_0: > + case PPB_BAR_1: > + switch ((Node->PciDev->PciBar[Node->Bar]).BarType) { > + > + case PciBarTypeIo16: > + case PciBarTypeIo32: > + case PciBarTypeMem32: > + case PciBarTypePMem32: > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (Node->PciDev->PciBar[Node->Bar]).Offset, > + 1, > + &Address > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + break; > + > + case PciBarTypeMem64: > + case PciBarTypePMem64: > + > + Address32 =3D (UINT32) (Address & 0x00000000FFFFFFFF); > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (Node->PciDev->PciBar[Node->Bar]).Offset, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) RShiftU64 (Address, 32); > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4), > + 1, > + &Address32 > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + break; > + > + default: > + break; > + } > + break; > + > + case PPB_IO_RANGE: > + > + Address32 =3D ((UINT32) (Address)) >> 8; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint8, > + 0x1C, > + 1, > + &Address32 > + ); > + > + Address32 >>=3D 8; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + 0x30, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) (Address + Node->Length - 1); > + Address32 =3D ((UINT32) (Address32)) >> 8; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint8, > + 0x1D, > + 1, > + &Address32 > + ); > + > + Address32 >>=3D 8; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + 0x32, > + 1, > + &Address32 > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + break; > + > + case PPB_MEM32_RANGE: > + > + Address32 =3D ((UINT32) (Address)) >> 16; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + 0x20, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) (Address + Node->Length - 1); > + Address32 =3D ((UINT32) (Address32)) >> 16; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + 0x22, > + 1, > + &Address32 > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + break; > + > + case PPB_PMEM32_RANGE: > + case PPB_PMEM64_RANGE: > + > + Address32 =3D ((UINT32) (Address)) >> 16; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + 0x24, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) (Address + Node->Length - 1); > + Address32 =3D ((UINT32) (Address32)) >> 16; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + 0x26, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) RShiftU64 (Address, 32); > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + 0x28, > + 1, > + &Address32 > + ); > + > + Address32 =3D (UINT32) RShiftU64 ((Address + Node->Length - 1), 32); > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + 0x2C, > + 1, > + &Address32 > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + break; > + > + default: > + break; > + } > +} > + > +/** > + Program parent bridge for Option Rom. > + > + @param PciDevice Pci device instance. > + @param OptionRomBase Base address for Option Rom. > + @param Enable Enable or disable PCI memory. > + > +**/ > +VOID > +ProgramUpstreamBridgeForRom ( > + IN PCI_IO_DEVICE *PciDevice, > + IN UINT32 OptionRomBase, > + IN BOOLEAN Enable > + ) > +{ > + PCI_IO_DEVICE *Parent; > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT16 Base; > + UINT16 Limit; > + // > + // For root bridge, just return. > + // > + Parent =3D PciDevice->Parent; > + while (Parent !=3D NULL) { > + if (!IS_PCI_BRIDGE (&Parent->Pci)) { > + break; > + } > + > + PciIo =3D &Parent->PciIo; > + > + // > + // Program PPB to only open a single <=3D 16MB aperture > + // > + if (Enable) { > + // > + // Only cover MMIO for Option ROM. > + // > + Base =3D (UINT16) (OptionRomBase >> 16); > + Limit =3D (UINT16) ((OptionRomBase + PciDevice->RomSize - 1) >> 16= ); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE0= 1, > Bridge.MemoryBase), 1, &Base); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE0= 1, > Bridge.MemoryLimit), 1, &Limit); > + > + PCI_ENABLE_COMMAND_REGISTER (Parent, > EFI_PCI_COMMAND_MEMORY_SPACE); > + } else { > + // > + // Cover 32bit MMIO for devices below the bridge. > + // > + if (Parent->PciBar[PPB_MEM32_RANGE].Length =3D=3D 0) { > + // > + // When devices under the bridge contains Option ROM and doesn't > require 32bit MMIO. > + // > + Base =3D (UINT16) gAllOne; > + Limit =3D (UINT16) gAllZero; > + } else { > + Base =3D (UINT16) ((UINT32) Parent- > >PciBar[PPB_MEM32_RANGE].BaseAddress >> 16); > + Limit =3D (UINT16) ((UINT32) (Parent- > >PciBar[PPB_MEM32_RANGE].BaseAddress > + + Parent->PciBar[PPB_MEM32_RANGE].Le= ngth - 1) >> > 16); > + } > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE0= 1, > Bridge.MemoryBase), 1, &Base); > + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE0= 1, > Bridge.MemoryLimit), 1, &Limit); > + > + PCI_DISABLE_COMMAND_REGISTER (Parent, > EFI_PCI_COMMAND_MEMORY_SPACE); > + } > + > + Parent =3D Parent->Parent; > + } > +} > + > +/** > + Test whether resource exists for a bridge. > + > + @param Bridge Point to resource node for a bridge. > + > + @retval TRUE There is resource on the given bridge. > + @retval FALSE There isn't resource on the given bridge. > + > +**/ > +BOOLEAN > +ResourceRequestExisted ( > + IN PCI_RESOURCE_NODE *Bridge > + ) > +{ > + if (Bridge !=3D NULL) { > + if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length !=3D 0) { > + return TRUE; > + } > + } > + > + return FALSE; > +} > + > +/** > + Initialize resource pool structure. > + > + @param ResourcePool Point to resource pool structure. This pool > + is reset to all zero when returned. > + @param ResourceType Type of resource. > + > +**/ > +VOID > +InitializeResourcePool ( > + IN OUT PCI_RESOURCE_NODE *ResourcePool, > + IN PCI_BAR_TYPE ResourceType > + ) > +{ > + ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE)); > + ResourcePool->ResType =3D ResourceType; > + ResourcePool->Signature =3D PCI_RESOURCE_SIGNATURE; > + InitializeListHead (&ResourcePool->ChildList); > +} > + > +/** > + Destroy given resource tree. > + > + @param Bridge PCI resource root node of resource tree. > + > +**/ > +VOID > +DestroyResourceTree ( > + IN PCI_RESOURCE_NODE *Bridge > + ) > +{ > + PCI_RESOURCE_NODE *Temp; > + LIST_ENTRY *CurrentLink; > + > + while (!IsListEmpty (&Bridge->ChildList)) { > + > + CurrentLink =3D Bridge->ChildList.ForwardLink; > + > + Temp =3D RESOURCE_NODE_FROM_LINK (CurrentLink); > + ASSERT (Temp); > + > + RemoveEntryList (CurrentLink); > + > + if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) { > + DestroyResourceTree (Temp); > + } > + > + FreePool (Temp); > + } > +} > + > +/** > + Insert resource padding for P2C. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +ResourcePaddingForCardBusBridge ( > + IN PCI_IO_DEVICE *PciDev, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ) > +{ > + PCI_RESOURCE_NODE *Node; > + > + Node =3D NULL; > + > + // > + // Memory Base/Limit Register 0 > + // Bar 1 decodes memory range 0 > + // > + Node =3D CreateResourceNode ( > + PciDev, > + 0x2000000, > + 0x1ffffff, > + 1, > + PciBarTypeMem32, > + PciResUsagePadding > + ); > + > + InsertResourceNode ( > + Mem32Node, > + Node > + ); > + > + // > + // Memory Base/Limit Register 1 > + // Bar 2 decodes memory range1 > + // > + Node =3D CreateResourceNode ( > + PciDev, > + 0x2000000, > + 0x1ffffff, > + 2, > + PciBarTypePMem32, > + PciResUsagePadding > + ); > + > + InsertResourceNode ( > + PMem32Node, > + Node > + ); > + > + // > + // Io Base/Limit > + // Bar 3 decodes io range 0 > + // > + Node =3D CreateResourceNode ( > + PciDev, > + 0x100, > + 0xff, > + 3, > + PciBarTypeIo16, > + PciResUsagePadding > + ); > + > + InsertResourceNode ( > + IoNode, > + Node > + ); > + > + // > + // Io Base/Limit > + // Bar 4 decodes io range 0 > + // > + Node =3D CreateResourceNode ( > + PciDev, > + 0x100, > + 0xff, > + 4, > + PciBarTypeIo16, > + PciResUsagePadding > + ); > + > + InsertResourceNode ( > + IoNode, > + Node > + ); > +} > + > +/** > + Program PCI Card device register for given resource node. > + > + @param Base Base address of PCI Card device to be programmed. > + @param Node Given resource node. > + > +**/ > +VOID > +ProgramP2C ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT64 Address; > + UINT64 TempAddress; > + UINT16 BridgeControl; > + > + Address =3D 0; > + PciIo =3D &(Node->PciDev->PciIo); > + > + Address =3D Base + Node->Offset; > + > + // > + // Indicate pci bus driver has allocated > + // resource for this device > + // It might be a temporary solution here since > + // pci device could have multiple bar > + // > + Node->PciDev->Allocated =3D TRUE; > + > + switch (Node->Bar) { > + > + case P2C_BAR_0: > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + (Node->PciDev->PciBar[Node->Bar]).Offset, > + 1, > + &Address > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + break; > + > + case P2C_MEM_1: > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_MEMORY_BASE_0, > + 1, > + &Address > + ); > + > + TempAddress =3D Address + Node->Length - 1; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_MEMORY_LIMIT_0, > + 1, > + &TempAddress > + ); > + > + if (Node->ResType =3D=3D PciBarTypeMem32) { > + // > + // Set non-prefetchable bit > + // > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + > + BridgeControl &=3D (UINT16) > ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + > + } else { > + // > + // Set prefetchable bit > + // > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + > + BridgeControl |=3D PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + } > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + Node->PciDev->PciBar[Node->Bar].BarType =3D Node->ResType; > + > + break; > + > + case P2C_MEM_2: > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_MEMORY_BASE_1, > + 1, > + &Address > + ); > + > + TempAddress =3D Address + Node->Length - 1; > + > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_MEMORY_LIMIT_1, > + 1, > + &TempAddress > + ); > + > + if (Node->ResType =3D=3D PciBarTypeMem32) { > + > + // > + // Set non-prefetchable bit > + // > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + > + BridgeControl &=3D (UINT16) > ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE); > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + > + } else { > + > + // > + // Set prefetchable bit > + // > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + > + BridgeControl |=3D PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint16, > + PCI_CARD_BRIDGE_CONTROL, > + 1, > + &BridgeControl > + ); > + } > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + Node->PciDev->PciBar[Node->Bar].BarType =3D Node->ResType; > + break; > + > + case P2C_IO_1: > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_IO_BASE_0_LOWER, > + 1, > + &Address > + ); > + > + TempAddress =3D Address + Node->Length - 1; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_IO_LIMIT_0_LOWER, > + 1, > + &TempAddress > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + Node->PciDev->PciBar[Node->Bar].BarType =3D Node->ResType; > + > + break; > + > + case P2C_IO_2: > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_IO_BASE_1_LOWER, > + 1, > + &Address > + ); > + > + TempAddress =3D Address + Node->Length - 1; > + PciIo->Pci.Write ( > + PciIo, > + EfiPciIoWidthUint32, > + PCI_CARD_IO_LIMIT_1_LOWER, > + 1, > + &TempAddress > + ); > + > + Node->PciDev->PciBar[Node->Bar].BaseAddress =3D Address; > + Node->PciDev->PciBar[Node->Bar].Length =3D Node->Length; > + Node->PciDev->PciBar[Node->Bar].BarType =3D Node->ResType; > + break; > + > + default: > + break; > + } > +} > + > +/** > + Create padding resource node. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +ApplyResourcePadding ( > + IN PCI_IO_DEVICE *PciDev, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ) > +{ > + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; > + PCI_RESOURCE_NODE *Node; > + UINT8 DummyBarIndex; > + > + DummyBarIndex =3D 0; > + Ptr =3D PciDev->ResourcePaddingDescriptors; > + > + while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc !=3D > ACPI_END_TAG_DESCRIPTOR) { > + > + if (Ptr->Desc =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType = =3D=3D > ACPI_ADDRESS_SPACE_TYPE_IO) { > + if (Ptr->AddrLen !=3D 0) { > + > + Node =3D CreateResourceNode ( > + PciDev, > + Ptr->AddrLen, > + Ptr->AddrRangeMax, > + DummyBarIndex, > + PciBarTypeIo16, > + PciResUsagePadding > + ); > + InsertResourceNode ( > + IoNode, > + Node > + ); > + } > + > + Ptr++; > + continue; > + } > + > + if (Ptr->Desc =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType = =3D=3D > ACPI_ADDRESS_SPACE_TYPE_MEM) { > + > + if (Ptr->AddrSpaceGranularity =3D=3D 32) { > + > + // > + // prefetchable > + // > + if (Ptr->SpecificFlag =3D=3D 0x6) { > + if (Ptr->AddrLen !=3D 0) { > + Node =3D CreateResourceNode ( > + PciDev, > + Ptr->AddrLen, > + Ptr->AddrRangeMax, > + DummyBarIndex, > + PciBarTypePMem32, > + PciResUsagePadding > + ); > + InsertResourceNode ( > + PMem32Node, > + Node > + ); > + } > + > + Ptr++; > + continue; > + } > + > + // > + // Non-prefetchable > + // > + if (Ptr->SpecificFlag =3D=3D 0) { > + if (Ptr->AddrLen !=3D 0) { > + Node =3D CreateResourceNode ( > + PciDev, > + Ptr->AddrLen, > + Ptr->AddrRangeMax, > + DummyBarIndex, > + PciBarTypeMem32, > + PciResUsagePadding > + ); > + InsertResourceNode ( > + Mem32Node, > + Node > + ); > + } > + > + Ptr++; > + continue; > + } > + } > + > + if (Ptr->AddrSpaceGranularity =3D=3D 64) { > + > + // > + // prefetchable > + // > + if (Ptr->SpecificFlag =3D=3D 0x6) { > + if (Ptr->AddrLen !=3D 0) { > + Node =3D CreateResourceNode ( > + PciDev, > + Ptr->AddrLen, > + Ptr->AddrRangeMax, > + DummyBarIndex, > + PciBarTypePMem64, > + PciResUsagePadding > + ); > + InsertResourceNode ( > + PMem64Node, > + Node > + ); > + } > + > + Ptr++; > + continue; > + } > + > + // > + // Non-prefetchable > + // > + if (Ptr->SpecificFlag =3D=3D 0) { > + if (Ptr->AddrLen !=3D 0) { > + Node =3D CreateResourceNode ( > + PciDev, > + Ptr->AddrLen, > + Ptr->AddrRangeMax, > + DummyBarIndex, > + PciBarTypeMem64, > + PciResUsagePadding > + ); > + InsertResourceNode ( > + Mem64Node, > + Node > + ); > + } > + > + Ptr++; > + continue; > + } > + } > + } > + > + Ptr++; > + } > +} > + > +/** > + Get padding resource for PCI-PCI bridge. > + > + @param PciIoDevice PCI-PCI bridge device instance. > + > + @note Feature flag PcdPciBusHotplugDeviceSupport determines > + whether need to pad resource for them. > +**/ > +VOID > +GetResourcePaddingPpb ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + if (gPciHotPlugInit !=3D NULL && FeaturePcdGet > (PcdPciBusHotplugDeviceSupport)) { > + if (PciIoDevice->ResourcePaddingDescriptors =3D=3D NULL) { > + GetResourcePaddingForHpb (PciIoDevice); > + } > + } > +} > + > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciResourceSupport.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciResourceSupport.h > new file mode 100644 > index 0000000000..2a33f77e55 > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciResourceSupport.h > @@ -0,0 +1,456 @@ > +/** @file > + PCI resources support functions declaration for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_RESOURCE_SUPPORT_H_ > +#define _EFI_PCI_RESOURCE_SUPPORT_H_ > + > +typedef enum { > + PciResUsageTypical, > + PciResUsagePadding > +} PCI_RESOURCE_USAGE; > + > +#define PCI_RESOURCE_SIGNATURE SIGNATURE_32 ('p', 'c', 'r', 'c') > + > +typedef struct { > + UINT32 Signature; > + LIST_ENTRY Link; > + LIST_ENTRY ChildList; > + PCI_IO_DEVICE *PciDev; > + UINT64 Alignment; > + UINT64 Offset; > + UINT8 Bar; > + PCI_BAR_TYPE ResType; > + UINT64 Length; > + BOOLEAN Reserved; > + PCI_RESOURCE_USAGE ResourceUsage; > + BOOLEAN Virtual; > +} PCI_RESOURCE_NODE; > + > +#define RESOURCE_NODE_FROM_LINK(a) \ > + CR (a, PCI_RESOURCE_NODE, Link, PCI_RESOURCE_SIGNATURE) > + > +/** > + The function is used to skip VGA range. > + > + @param Start Returned start address including VGA range. > + @param Length The length of VGA range. > + > +**/ > +VOID > +SkipVGAAperture ( > + OUT UINT64 *Start, > + IN UINT64 Length > + ); > + > +/** > + This function is used to skip ISA aliasing aperture. > + > + @param Start Returned start address including ISA aliasing aperture= . > + @param Length The length of ISA aliasing aperture. > + > +**/ > +VOID > +SkipIsaAliasAperture ( > + OUT UINT64 *Start, > + IN UINT64 Length > + ); > + > +/** > + This function inserts a resource node into the resource list. > + The resource list is sorted in descend order. > + > + @param Bridge PCI resource node for bridge. > + @param ResNode Resource node want to be inserted. > + > +**/ > +VOID > +InsertResourceNode ( > + IN OUT PCI_RESOURCE_NODE *Bridge, > + IN PCI_RESOURCE_NODE *ResNode > + ); > + > +/** > + This routine is used to merge two different resource trees in need of > + resource degradation. > + > + For example, if an upstream PPB doesn't support, > + prefetchable memory decoding, the PCI bus driver will choose to call t= his > function > + to merge prefetchable memory resource list into normal memory list. > + > + If the TypeMerge is TRUE, Res resource type is changed to the type of > destination resource > + type. > + If Dst is NULL or Res is NULL, ASSERT (). > + > + @param Dst Point to destination resource tree. > + @param Res Point to source resource tree. > + @param TypeMerge If the TypeMerge is TRUE, Res resource type is > changed to the type of > + destination resource type. > + > +**/ > +VOID > +MergeResourceTree ( > + IN PCI_RESOURCE_NODE *Dst, > + IN PCI_RESOURCE_NODE *Res, > + IN BOOLEAN TypeMerge > + ); > + > +/** > + This function is used to calculate the IO16 aperture > + for a bridge. > + > + @param Bridge PCI resource node for bridge. > + > +**/ > +VOID > +CalculateApertureIo16 ( > + IN PCI_RESOURCE_NODE *Bridge > + ); > + > +/** > + This function is used to calculate the resource aperture > + for a given bridge device. > + > + @param Bridge PCI resource node for given bridge device. > + > +**/ > +VOID > +CalculateResourceAperture ( > + IN PCI_RESOURCE_NODE *Bridge > + ); > + > +/** > + Get IO/Memory resource info for given PCI device. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO . > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +GetResourceFromDevice ( > + IN PCI_IO_DEVICE *PciDev, > + IN OUT PCI_RESOURCE_NODE *IoNode, > + IN OUT PCI_RESOURCE_NODE *Mem32Node, > + IN OUT PCI_RESOURCE_NODE *PMem32Node, > + IN OUT PCI_RESOURCE_NODE *Mem64Node, > + IN OUT PCI_RESOURCE_NODE *PMem64Node > + ); > + > +/** > + This function is used to create a resource node. > + > + @param PciDev Pci device instance. > + @param Length Length of Io/Memory resource. > + @param Alignment Alignment of resource. > + @param Bar Bar index. > + @param ResType Type of resource: IO/Memory. > + @param ResUsage Resource usage. > + > + @return PCI resource node created for given PCI device. > + NULL means PCI resource node is not created. > + > +**/ > +PCI_RESOURCE_NODE * > +CreateResourceNode ( > + IN PCI_IO_DEVICE *PciDev, > + IN UINT64 Length, > + IN UINT64 Alignment, > + IN UINT8 Bar, > + IN PCI_BAR_TYPE ResType, > + IN PCI_RESOURCE_USAGE ResUsage > + ); > + > +/** > + This function is used to create a IOV VF resource node. > + > + @param PciDev Pci device instance. > + @param Length Length of Io/Memory resource. > + @param Alignment Alignment of resource. > + @param Bar Bar index. > + @param ResType Type of resource: IO/Memory. > + @param ResUsage Resource usage. > + > + @return PCI resource node created for given VF PCI device. > + NULL means PCI resource node is not created. > + > +**/ > +PCI_RESOURCE_NODE * > +CreateVfResourceNode ( > + IN PCI_IO_DEVICE *PciDev, > + IN UINT64 Length, > + IN UINT64 Alignment, > + IN UINT8 Bar, > + IN PCI_BAR_TYPE ResType, > + IN PCI_RESOURCE_USAGE ResUsage > + ); > + > +/** > + This function is used to extract resource request from > + device node list. > + > + @param Bridge Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +CreateResourceMap ( > + IN PCI_IO_DEVICE *Bridge, > + IN OUT PCI_RESOURCE_NODE *IoNode, > + IN OUT PCI_RESOURCE_NODE *Mem32Node, > + IN OUT PCI_RESOURCE_NODE *PMem32Node, > + IN OUT PCI_RESOURCE_NODE *Mem64Node, > + IN OUT PCI_RESOURCE_NODE *PMem64Node > + ); > + > +/** > + This function is used to do the resource padding for a specific platfo= rm. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +ResourcePaddingPolicy ( > + IN PCI_IO_DEVICE *PciDev, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ); > + > +/** > + This function is used to degrade resource if the upstream bridge > + doesn't support certain resource. Degradation path is > + PMEM64 -> MEM64 -> MEM32 > + PMEM64 -> PMEM32 -> MEM32 > + IO32 -> IO16. > + > + @param Bridge Pci device instance. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +DegradeResource ( > + IN PCI_IO_DEVICE *Bridge, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ); > + > +/** > + Test whether bridge device support decode resource. > + > + @param Bridge Bridge device instance. > + @param Decode Decode type according to resource type. > + > + @return TRUE The bridge device support decode resource. > + @return FALSE The bridge device don't support decode resource. > + > +**/ > +BOOLEAN > +BridgeSupportResourceDecode ( > + IN PCI_IO_DEVICE *Bridge, > + IN UINT32 Decode > + ); > + > +/** > + This function is used to program the resource allocated > + for each resource node under specified bridge. > + > + @param Base Base address of resource to be programmed. > + @param Bridge PCI resource node for the bridge device. > + > + @retval EFI_SUCCESS Successfully to program all resources > + on given PCI bridge device. > + @retval EFI_OUT_OF_RESOURCES Base is all one. > + > +**/ > +EFI_STATUS > +ProgramResource ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Bridge > + ); > + > +/** > + Program Bar register for PCI device. > + > + @param Base Base address for PCI device resource to be programmed. > + @param Node Point to resource node structure. > + > +**/ > +VOID > +ProgramBar ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ); > + > +/** > + Program IOV VF Bar register for PCI device. > + > + @param Base Base address for PCI device resource to be programmed. > + @param Node Point to resource node structure. > + > +**/ > +EFI_STATUS > +ProgramVfBar ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ); > + > +/** > + Program PCI-PCI bridge aperture. > + > + @param Base Base address for resource. > + @param Node Point to resource node structure. > + > +**/ > +VOID > +ProgramPpbApperture ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ); > + > +/** > + Program parent bridge for Option Rom. > + > + @param PciDevice Pci device instance. > + @param OptionRomBase Base address for Option Rom. > + @param Enable Enable or disable PCI memory. > + > +**/ > +VOID > +ProgramUpstreamBridgeForRom ( > + IN PCI_IO_DEVICE *PciDevice, > + IN UINT32 OptionRomBase, > + IN BOOLEAN Enable > + ); > + > +/** > + Test whether resource exists for a bridge. > + > + @param Bridge Point to resource node for a bridge. > + > + @retval TRUE There is resource on the given bridge. > + @retval FALSE There isn't resource on the given bridge. > + > +**/ > +BOOLEAN > +ResourceRequestExisted ( > + IN PCI_RESOURCE_NODE *Bridge > + ); > + > +/** > + Initialize resource pool structure. > + > + @param ResourcePool Point to resource pool structure. This pool > + is reset to all zero when returned. > + @param ResourceType Type of resource. > + > +**/ > +VOID > +InitializeResourcePool ( > + IN OUT PCI_RESOURCE_NODE *ResourcePool, > + IN PCI_BAR_TYPE ResourceType > + ); > + > +/** > + Destroy given resource tree. > + > + @param Bridge PCI resource root node of resource tree. > + > +**/ > +VOID > +DestroyResourceTree ( > + IN PCI_RESOURCE_NODE *Bridge > + ); > + > +/** > + Insert resource padding for P2C. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +ResourcePaddingForCardBusBridge ( > + IN PCI_IO_DEVICE *PciDev, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ); > + > +/** > + Program PCI Card device register for given resource node. > + > + @param Base Base address of PCI Card device to be programmed. > + @param Node Given resource node. > + > +**/ > +VOID > +ProgramP2C ( > + IN UINT64 Base, > + IN PCI_RESOURCE_NODE *Node > + ); > + > +/** > + Create padding resource node. > + > + @param PciDev Pci device instance. > + @param IoNode Resource info node for IO. > + @param Mem32Node Resource info node for 32-bit memory. > + @param PMem32Node Resource info node for 32-bit Prefetchable > Memory. > + @param Mem64Node Resource info node for 64-bit memory. > + @param PMem64Node Resource info node for 64-bit Prefetchable > Memory. > + > +**/ > +VOID > +ApplyResourcePadding ( > + IN PCI_IO_DEVICE *PciDev, > + IN PCI_RESOURCE_NODE *IoNode, > + IN PCI_RESOURCE_NODE *Mem32Node, > + IN PCI_RESOURCE_NODE *PMem32Node, > + IN PCI_RESOURCE_NODE *Mem64Node, > + IN PCI_RESOURCE_NODE *PMem64Node > + ); > + > +/** > + Get padding resource for PCI-PCI bridge. > + > + @param PciIoDevice PCI-PCI bridge device instance. > + > + @note Feature flag PcdPciBusHotplugDeviceSupport determines > + whether need to pad resource for them. > +**/ > +VOID > +GetResourcePaddingPpb ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +#endif > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciRomTable.c > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciRomTable.c > new file mode 100644 > index 0000000000..507aed5cfe > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciRomTable.c > @@ -0,0 +1,135 @@ > +/** @file > + Set up ROM Table for PCI Bus module. > + > +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PciBus.h" > + > +// > +// PCI ROM image information > +// > +typedef struct { > + EFI_HANDLE ImageHandle; > + UINTN Seg; > + UINT8 Bus; > + UINT8 Dev; > + UINT8 Func; > + VOID *RomImage; > + UINT64 RomSize; > +} PCI_ROM_IMAGE; > + > +UINTN mNumberOfPciRomImages =3D 0; > +UINTN mMaxNumberOfPciRomImages =3D 0; > +PCI_ROM_IMAGE *mRomImageTable =3D NULL; > + > +/** > + Add the Rom Image to internal database for later PCI light enumeration= . > + > + @param ImageHandle Option Rom image handle. > + @param Seg Segment of PCI space. > + @param Bus Bus NO of PCI space. > + @param Dev Dev NO of PCI space. > + @param Func Func NO of PCI space. > + @param RomImage Option Rom buffer. > + @param RomSize Size of Option Rom buffer. > +**/ > +VOID > +PciRomAddImageMapping ( > + IN EFI_HANDLE ImageHandle, > + IN UINTN Seg, > + IN UINT8 Bus, > + IN UINT8 Dev, > + IN UINT8 Func, > + IN VOID *RomImage, > + IN UINT64 RomSize > + ) > +{ > + UINTN Index; > + PCI_ROM_IMAGE *NewTable; > + > + for (Index =3D 0; Index < mNumberOfPciRomImages; Index++) { > + if (mRomImageTable[Index].Seg =3D=3D Seg && > + mRomImageTable[Index].Bus =3D=3D Bus && > + mRomImageTable[Index].Dev =3D=3D Dev && > + mRomImageTable[Index].Func =3D=3D Func) { > + // > + // Expect once RomImage and RomSize are recorded, they will be pas= sed > in > + // later when updating ImageHandle > + // > + ASSERT ((mRomImageTable[Index].RomImage =3D=3D NULL) || (RomImage > =3D=3D mRomImageTable[Index].RomImage)); > + ASSERT ((mRomImageTable[Index].RomSize =3D=3D 0 ) || (RomSize = =3D=3D > mRomImageTable[Index].RomSize )); > + break; > + } > + } > + > + if (Index =3D=3D mNumberOfPciRomImages) { > + // > + // Rom Image Table buffer needs to grow. > + // > + if (mNumberOfPciRomImages =3D=3D mMaxNumberOfPciRomImages) { > + NewTable =3D ReallocatePool ( > + mMaxNumberOfPciRomImages * sizeof (PCI_ROM_IMAGE), > + (mMaxNumberOfPciRomImages + 0x20) * sizeof > (PCI_ROM_IMAGE), > + mRomImageTable > + ); > + if (NewTable =3D=3D NULL) { > + return ; > + } > + > + mRomImageTable =3D NewTable; > + mMaxNumberOfPciRomImages +=3D 0x20; > + } > + // > + // Record the new PCI device > + // > + mRomImageTable[Index].Seg =3D Seg; > + mRomImageTable[Index].Bus =3D Bus; > + mRomImageTable[Index].Dev =3D Dev; > + mRomImageTable[Index].Func =3D Func; > + mNumberOfPciRomImages++; > + } > + > + mRomImageTable[Index].ImageHandle =3D ImageHandle; > + mRomImageTable[Index].RomImage =3D RomImage; > + mRomImageTable[Index].RomSize =3D RomSize; > +} > + > +/** > + Get Option rom driver's mapping for PCI device. > + > + @param PciIoDevice Device instance. > + > + @retval TRUE Found Image mapping. > + @retval FALSE Cannot found image mapping. > + > +**/ > +BOOLEAN > +PciRomGetImageMapping ( > + IN PCI_IO_DEVICE *PciIoDevice > + ) > +{ > + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; > + UINTN Index; > + > + PciRootBridgeIo =3D PciIoDevice->PciRootBridgeIo; > + > + for (Index =3D 0; Index < mNumberOfPciRomImages; Index++) { > + if (mRomImageTable[Index].Seg =3D=3D PciRootBridgeIo->SegmentNumber > && > + mRomImageTable[Index].Bus =3D=3D PciIoDevice->BusNumber = && > + mRomImageTable[Index].Dev =3D=3D PciIoDevice->DeviceNumber = && > + mRomImageTable[Index].Func =3D=3D PciIoDevice->FunctionNumber = ) { > + > + if (mRomImageTable[Index].ImageHandle !=3D NULL) { > + AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle, NULL)= ; > + } > + PciIoDevice->PciIo.RomImage =3D mRomImageTable[Index].RomImage; > + PciIoDevice->PciIo.RomSize =3D mRomImageTable[Index].RomSize; > + return TRUE; > + } > + } > + > + return FALSE; > +} > diff --git > a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciRomTable.h > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciRomTable.h > new file mode 100644 > index 0000000000..fb356bd6de > --- /dev/null > +++ > b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/P > ciBusDxe/PciRomTable.h > @@ -0,0 +1,48 @@ > +/** @file > + Set up ROM Table for PCI Bus module. > + > +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _EFI_PCI_ROM_TABLE_H_ > +#define _EFI_PCI_ROM_TABLE_H_ > + > +/** > + Add the Rom Image to internal database for later PCI light enumeration= . > + > + @param ImageHandle Option Rom image handle. > + @param Seg Segment of PCI space. > + @param Bus Bus NO of PCI space. > + @param Dev Dev NO of PCI space. > + @param Func Func NO of PCI space. > + @param RomImage Option Rom buffer. > + @param RomSize Size of Option Rom buffer. > +**/ > +VOID > +PciRomAddImageMapping ( > + IN EFI_HANDLE ImageHandle, > + IN UINTN Seg, > + IN UINT8 Bus, > + IN UINT8 Dev, > + IN UINT8 Func, > + IN VOID *RomImage, > + IN UINT64 RomSize > + ); > + > +/** > + Get Option rom driver's mapping for PCI device. > + > + @param PciIoDevice Device instance. > + > + @retval TRUE Found Image mapping. > + @retval FALSE Cannot found image mapping. > + > +**/ > +BOOLEAN > +PciRomGetImageMapping ( > + IN PCI_IO_DEVICE *PciIoDevice > + ); > + > +#endif > -- > 2.25.0.windows.1 >=20 >=20 > Please consider the environment before printing this email. >=20 > The information contained in this message may be confidential and > proprietary to American Megatrends (AMI). This communication is intended > to be read only by the individual or entity to whom it is addressed or by= their > designee. If the reader of this message is not the intended recipient, yo= u are > on notice that any distribution of this message, in any form, is strictly > prohibited. Please promptly notify the sender by reply e-mail or by > telephone at 770-246-8600, and then delete or destroy all copies of the > transmission.