From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-BN8-obe.outbound.protection.outlook.com (NAM12-BN8-obe.outbound.protection.outlook.com [40.107.237.51]) by mx.groups.io with SMTP id smtpd.web11.865.1623941735808890108 for ; Thu, 17 Jun 2021 07:55:37 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@ami.com header.s=selector1 header.b=NsfdoNB5; spf=pass (domain: ami.com, ip: 40.107.237.51, mailfrom: manickavasakamk@ami.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=oUN96qIx2amvmuTadoLzUXjmEbTRkIILNt9OCBNa75vmKQUnp2SRcGFCblDr72mqQKrZ+8s361OkiEhHunN1KwnQd25eYOL+gBMGd1Zo8YJWsNCpmyA26tPDZkj6ZrNqF/VV1dgJMXk24Y1p04tN6yS5KYIzE/2tvgaKQX17RGNwV/s7slFVzU/FsKeH2BB++aRDF7U7Dm5Twb6liKB7MUKDQY3es4XCb6BhvB8mXhlqkpzVbzR2nVgBldbeX9YrjNyHfZHChFNDz7m5Yc/Pfv/uyOjd4go0iAjDfcoOqLjEUw9xeEOwMUcNjLosV35Tof4t+kHK3UJ4xw1YtMqIXg== 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=2Gg/iuqRblsM4U5DilNDHBp96GUQ1XpSxHLon9PjlJc=; b=c6cIVrPi+iLUrerZ/mfngN08v5zEIOofKOyXO2UlIuucvmgrR1LJv9ZnGf+Don0X9lbcEw4004/+ms1l/iKmoCKZegQ20BjuGQvFcHdhO5erVXAsA5Cc8HWfpIzVGPybHw7qhjsU7L0Ya1rqgEMYIGmi3b53hlahZ9kZS8ZRg77ZtNAmz8WFN/6c+vqJ4bTSNCCDKkHOCoOvt34XZn8G5hhhTJrdsYe7+m3VKGsZqXHdk+JkecLSdaugSxH6xyvn7uv5Hb5CL9ucFsXoIGYMDgyj2MdTDNN2Q2KjaOzFZTpv77ZZH0x6Y285cT1hXeYa4GeUj1zGy77M792eB+wUMw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=ami.com; dmarc=pass action=none header.from=ami.com; dkim=pass header.d=ami.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ami.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=2Gg/iuqRblsM4U5DilNDHBp96GUQ1XpSxHLon9PjlJc=; b=NsfdoNB5wYmZ4Ye7LMiX+zJKVRa/vlPbsFI1p6lKKKj9rwA9pea1kZpRTNebtMcPJ+ROdNGX6wL0uqQCbKVXYAbSOykpyKsLXyQVf6+OHMbhCV5rzPO86s63dLRRoP4gyzNKvPGTJ4sBcr9DceHq+jclYIqZVM9B/8siCZ6RfCs= Received: from PH0PR10MB4408.namprd10.prod.outlook.com (2603:10b6:510:39::16) by PH0PR10MB4502.namprd10.prod.outlook.com (2603:10b6:510:31::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4242.18; Thu, 17 Jun 2021 14:55:31 +0000 Received: from PH0PR10MB4408.namprd10.prod.outlook.com ([fe80::c578:856e:c894:d2b0]) by PH0PR10MB4408.namprd10.prod.outlook.com ([fe80::c578:856e:c894:d2b0%9]) with mapi id 15.20.4242.021; Thu, 17 Jun 2021 14:55:30 +0000 From: "manickavasakam karpagavinayagam" To: gaoliming , "devel@edk2.groups.io" CC: Harikrishna Doppalapudi Subject: =?UTF-8?B?UmU6IFtFWFRFUk5BTF0g5Zue5aSNOiBbZWRrMi1kZXZlbF0gW2VkazItcGxhdGZvcm1zXSBbUEFUQ0ggVjEgMC8yXSBTdXBwb3J0IGZvciBUaW9nYVBhc3MgUGxhdGZvcm0gYW5kIE92ZXJyaWRlIGdlbmVyaWMgUGNpQnVzIERyaXZlciB3aXRo?= Thread-Topic: =?utf-8?B?W0VYVEVSTkFMXSDlm57lpI06IFtlZGsyLWRldmVsXSBbZWRrMi1wbGF0Zm9y?= =?utf-8?B?bXNdIFtQQVRDSCBWMSAwLzJdIFN1cHBvcnQgZm9yIFRpb2dhUGFzcyBQbGF0?= =?utf-8?Q?form_and_Override_generic_PciBus_Driver_with?= Thread-Index: AQH/JkFWvYqPL60rlTiovh4SVEZEmqrH+33wgADH9nA= Date: Thu, 17 Jun 2021 14:55:30 +0000 Message-ID: References: <006001d76324$55160d40$ff4227c0$@byosoft.com.cn> In-Reply-To: <006001d76324$55160d40$ff4227c0$@byosoft.com.cn> Accept-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: authentication-results: byosoft.com.cn; dkim=none (message not signed) header.d=none;byosoft.com.cn; dmarc=none action=none header.from=ami.com; x-originating-ip: [63.147.10.3] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: a9538bc8-bd95-4efb-747e-08d9319ff3d1 x-ms-traffictypediagnostic: PH0PR10MB4502: x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:2958; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: LdDPWb6qsijhlKyJoA4ONWHzo9a8fzCm98DPzOnN3ZAeG0s4hK1is/XONmhbFNWAJybjhK9GvFXSc3pz4kitzSpeTrHnHp7igJ5DTJ9tIs4DQwHp78O4uSgzgVVp8P0wy2R/nEI1QiikQTEPPkEhU/iiXl9dSu5EjmG8cV2VnncC6pMAZ5MaMu2TA8YB396FbcgDpeNwle0owsbMxnuYr/titOK5K66QcbRigsCfAfK+18rxtm2BvOA03O2NQ8lkPrUqO1PzroF7zMZVf8+ZQyQJhb8nCk0d/EUnBQbGD9ycjRvBAcnvlFjuOJlOGVd2MRkSC2cSxJrv4KqTQJ1B8e09HSnlRy3mcjxzDOnBPLe0qGKGvXTxkb66qbhsPfHt74BXCmg47/ZRju53y5iExz/hmzx8wxfmksTOjJFKv69jLI5L7s14N+9XbFqL8EHUral7bXjbfV2NQK/FWVuxbvyvZUWDfvgD9YAdiwQRXDf6ugDP+AvvO4fKxzVdGbmwzILN2zPMeF8iYeefieNyEfcL/iUgu9rNZ301+KVEhla5banax8e84XsZ2P+4yhRu4aMRHjf4/ixPk3S+M93xIwXP6s5llhhiIJ76B/+4G25E2GR2nXCsAQ8E0yGJZoku88xE51ww+ZMxwLXHopiOVf75r8xK7ptmlLtLzBjxpDa36dmdyG5/JLEqxn2R99zRGkGHyjYmBsOdLjpkZpBILCIZ0i7dL1ZcvdUpPdgqFBzW7JI0Fm+TFCDvt9I8rR98WHmS9qjBTRXpjgzGOgzZ4g== x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR10MB4408.namprd10.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(346002)(136003)(366004)(376002)(39840400004)(396003)(71200400001)(2906002)(83380400001)(66446008)(166002)(224303003)(99936003)(86362001)(316002)(76236003)(30864003)(53546011)(26005)(66616009)(76116006)(8936002)(66946007)(186003)(7696005)(110136005)(966005)(64756008)(4326008)(478600001)(122000001)(66556008)(66476007)(55016002)(9686003)(38100700002)(52536014)(5660300002)(33656002)(6506007)(41533002);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?B?Q0M2N2lqU0Vqd2dJc09nNEY4c0hieENieDJGQXcrN1I0eDEvMis3U2l1bVNE?= =?utf-8?B?ZURoemNDOUxmOEVJVHkweDQ3U2h4OVpjMTJTZkZXQUNqTElWUFJmVjVrRms3?= =?utf-8?B?V3AwcDdtSFNwcWgvSTN0bXFrVXNrd3VVc3Z0dk9YNEtSczIwbzNmcDBOT045?= =?utf-8?B?NGFSalVoRHp6YVFmemhYRTJRNko0QzV5bGYvazJOKzNLSG9ScHpvKzMzbVZW?= =?utf-8?B?VmxETW1Jd0xVMEt6UGhIdXRyanhjalUvaGRESFA2RHRlaW9zbi9jS0VJTkMx?= =?utf-8?B?MTVuV2EyVVBIcEw2a2hXT2g0SXZqYUIrRDdWZ0hqald0MHZiRjVEYWZBV3c2?= =?utf-8?B?VkQ3R0RsYzhkOS9wbHVnaWFyQU9TZnVyL3lUQVI2UTVSOXdnRjk1QUdrLzdW?= =?utf-8?B?c09ja1F6ZkRwQ0VkZ3p3bW50RkpDVlg4TFdPMzBiU3VxUXI2SjR6N1hOSm9K?= =?utf-8?B?R0dxWk1zMG5VNEo3QmJiV1NtWEgrRmpvVENCTmhVZGVBb2d6MEgzcHFEUVBC?= =?utf-8?B?OXBuYmZ4U1NOQUt2QitGa1JKYTVtTzdVaktkSW5Gcm05c05ralRNYnBlQnZT?= =?utf-8?B?KzFTWEUyaDNOczQ1a2owaVpEZ3lUaGVZaFg2Zi96eGtvV3FRR3VCWENGc3RS?= =?utf-8?B?OUdYK2lISHlOR3dCUTVNRlc5Tnh1QkEreEdGekpxYjkwcXUvVGQwRE1HNWZq?= =?utf-8?B?S0FKTzJLbks0VDV2RXlkNWNldEpoT2xRZUpRNmJzdEpXREFtM09yTUJnMjZ0?= =?utf-8?B?ckhhZUcweFo1RVRIeUtSYmpSNGVFdFFTcS9RQlpSOGZ5ZWdmSmlBdjBQVFBE?= =?utf-8?B?Ri93bW5ETlJKU2UyV2FwWm8xeis4b0ltWlgvWjFSQmptSytnN1hzYmQyQzhq?= =?utf-8?B?TG96OExnbnd1ZWg4V1l1VEk3VHBIT2tjK1lLaDVnQ0xKRHBWSDR3SUlzd1Y5?= =?utf-8?B?TjZBZHQ2Q0Rwb0trTEdvMTkwSmZOc04xcDVZa05OZzBZTTdXaWw3anVMY1lz?= =?utf-8?B?STMvcnN2OHNuV09VbHcrUGliRS8rbTdsZ2JZMER6Ti9FaE95ZEhyc0tlVzZ1?= =?utf-8?B?L04yNEN4WFpHTWxIaks1V2xla1BKM3Q1aFkzb1oyejJ3U2xocWJ5TEh5eFp0?= =?utf-8?B?NzJHcWpZWVFPMzBKZ1RsRUwvV3NYWFVwNm42cjd3YWtjK3ZLcGZTTWR2MkVN?= =?utf-8?B?VkV2aTNidHBUWUgyWFd3UnorcmFTVjdaUTRja25IS0xHd0hxODExVERkMU9N?= =?utf-8?B?Mk4xT2JtSXhYVW1HRDFDVkpvakRLaWVjNHVxLzYrZG1LZzFtNlpFNUJ4c25R?= =?utf-8?B?Y3gxL1hhUFJ2YU9nMklkKzdMYnNnTW1ZMVBpTzNqVVhUWEJwSk52Q2lsWEhR?= =?utf-8?B?Ty9NOXE3bWZCNHh6U3dTSENiSFA5YTE0bmQvd2Vtb0tYWnVxVjdmVEZiZUhw?= =?utf-8?B?TEloTEMwR01jRG1xMXkxRmdVSlI0QUl1bTZVZjhSR1BUM1RZUFFlM1M1Q0pl?= =?utf-8?B?SHJkTUc3NEl2TEtqUVB0SW9hS20wdVp3d0tBNmdqT09JUE1RdDJuU1N3YUZQ?= =?utf-8?B?NUFuVzJpYmdhMFFFL0YvejZzYzVEU1RybTdSR0t4endCTEpESXJwYlJielU0?= =?utf-8?B?RGN1THE5Q1FNQ2Y5U2R5TFhvWmRTdEpYVW9MMmd6cjdhblJNV2JtS0VmSlJq?= =?utf-8?B?ZFpldmx5eGVxRG9zZDhBVUhkalNEWUZIYm9WMTZSd0pqQ0VLR3lYOGpXRVZU?= =?utf-8?Q?LCxbwfNAIRLwsx7RHs=3D?= MIME-Version: 1.0 X-OriginatorOrg: ami.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PH0PR10MB4408.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: a9538bc8-bd95-4efb-747e-08d9319ff3d1 X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Jun 2021 14:55:30.6481 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 27e97857-e15f-486c-b58e-86c2b3040f93 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 1cvDG51r6nqDhm4Px+d9jH/9ESuNT12lJWN2mvBg3dn1t/QU+xqLw6gngoCid8yknWp6XjVDQzQlIH9Ca3ring== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR10MB4502 X-Groupsio-MsgNum: 76675 Content-Language: en-US Content-Type: multipart/mixed; boundary="_004_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_" --_004_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_ Content-Type: multipart/alternative; boundary="_000_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_" --_000_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 TGltaW5nIDoNCg0KQmVsb3cgZW1haWwgaXMgdGhlIGNvdmVyIGxldHRlciBhbmQgdGhpcyBwYXRj aCBzZXJpZXMgaGFzIHR3byBjaGFuZ2VzLiBTdXJlIG5leHQgdGltZSwgd2lsbCBhZGQgbW9yZSBj b21tZW50cyBpbiB0aGUgY292ZXIgbGV0dGVyIGFsc28uDQpQbGVhc2UgcmVmZXIgdGhlIGF0dGFj aGVkIGVtYWlsIGFuZCBpdCBoYXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIFBDSUJVUyBvdmVycmlk ZSBjaGFuZ2VzLiBQQ0lCVVMgb3ZlcnJpZGUgaXMgZG9uZSBiYXNlZCBvbiB0aGUgcGxhdGZvcm0g c2lnaHRpbmcgYW5kIGl0IGNhbuKAmXQgYmUgZ2VuZXJpYy4NCg0KVGhhbmsgeW91DQoNCi1NYW5p Yw0KDQpGcm9tOiBnYW9saW1pbmcgPGdhb2xpbWluZ0BieW9zb2Z0LmNvbS5jbj4NClNlbnQ6IFdl ZG5lc2RheSwgSnVuZSAxNiwgMjAyMSAxMDo1NiBQTQ0KVG86IGRldmVsQGVkazIuZ3JvdXBzLmlv OyBNYW5pY2thdmFzYWthbSBLYXJwYWdhdmluYXlhZ2FtIDxtYW5pY2thdmFzYWthbWtAYW1pLmNv bT4NClN1YmplY3Q6IFtFWFRFUk5BTF0g5Zue5aSNOiBbZWRrMi1kZXZlbF0gW2VkazItcGxhdGZv cm1zXSBbUEFUQ0ggVjEgMC8yXSBTdXBwb3J0IGZvciBUaW9nYVBhc3MgUGxhdGZvcm0gYW5kIE92 ZXJyaWRlIGdlbmVyaWMgUGNpQnVzIERyaXZlciB3aXRoDQoNCg0KKipDQVVUSU9OOiBUaGUgZS1t YWlsIGJlbG93IGlzIGZyb20gYW4gZXh0ZXJuYWwgc291cmNlLiBQbGVhc2UgZXhlcmNpc2UgY2F1 dGlvbiBiZWZvcmUgb3BlbmluZyBhdHRhY2htZW50cywgY2xpY2tpbmcgbGlua3MsIG9yIGZvbGxv d2luZyBndWlkYW5jZS4qKg0KDQpQbGVhc2UgZm9sbG93IGh0dHBzOi8vZ2l0aHViLmNvbS90aWFu b2NvcmUvdGlhbm9jb3JlLmdpdGh1Yi5pby93aWtpL0NvbW1pdC1NZXNzYWdlLUZvcm1hdDxodHRw czovL25hbTEyLnNhZmVsaW5rcy5wcm90ZWN0aW9uLm91dGxvb2suY29tLz91cmw9aHR0cHMlM0El MkYlMkZnaXRodWIuY29tJTJGdGlhbm9jb3JlJTJGdGlhbm9jb3JlLmdpdGh1Yi5pbyUyRndpa2kl MkZDb21taXQtTWVzc2FnZS1Gb3JtYXQmZGF0YT0wNCU3QzAxJTdDbWFuaWNrYXZhc2FrYW1rJTQw YW1pLmNvbSU3QzQ3OGQzOGZmMjM2YTQ5NmIxZjhhMDhkOTMxM2I3OGI1JTdDMjdlOTc4NTdlMTVm NDg2Y2I1OGU4NmMyYjMwNDBmOTMlN0MxJTdDMCU3QzYzNzU5NDk1Mzc3OTE1MTg0MSU3Q1Vua25v d24lN0NUV0ZwYkdac2IzZDhleUpXSWpvaU1DNHdMakF3TURBaUxDSlFJam9pVjJsdU16SWlMQ0pC VGlJNklrMWhhV3dpTENKWFZDSTZNbjAlM0QlN0MxMDAwJnNkYXRhPVJoUCUyQkJ5NjJ1bnhqUWF1 dnplMDZUanpSZXElMkZKZlVncTclMkI5RFIwUjhrTlklM0QmcmVzZXJ2ZWQ9MD4gdG8gdXBkYXRl IHRoZSBjb21taXQgbWVzc2FnZSBmb3JtYXQuDQoNCkFuZCwgZm9yIHRoZSBvdmVycmlkZSBQY2lC dXMgbW9kdWxlLCBjYW4geW91IGdpdmUgbW9yZSBkZXRhaWwgd2h5IG5lZWQgdG8gb3ZlcnJpZGUg UGNpQnVzPyBJcyBpdCBwb3NzaWJsZSB0byB1cGRhdGUgRWRrMiBNZGVNb2R1bGVQa2cgUGNpQnVz IHRvIG1lZXQgdGhlIHBsYXRmb3JtIHJlcXVpcmVtZW50Pw0KDQpUaGFua3MNCkxpbWluZw0K5Y+R 5Lu25Lq6OiBkZXZlbEBlZGsyLmdyb3Vwcy5pbzxtYWlsdG86ZGV2ZWxAZWRrMi5ncm91cHMuaW8+ IDxkZXZlbEBlZGsyLmdyb3Vwcy5pbzxtYWlsdG86ZGV2ZWxAZWRrMi5ncm91cHMuaW8+PiDku6Po oaggbWFuaWNrYXZhc2FrYW0ga2FycGFnYXZpbmF5YWdhbQ0K5Y+R6YCB5pe26Ze0OiAyMDIx5bm0 NuaciDE35pelIDc6MDUNCuaUtuS7tuS6ujogZGV2ZWxAZWRrMi5ncm91cHMuaW88bWFpbHRvOmRl dmVsQGVkazIuZ3JvdXBzLmlvPg0K5Li76aKYOiBbZWRrMi1kZXZlbF0gW2VkazItcGxhdGZvcm1z XSBbUEFUQ0ggVjEgMC8yXSBTdXBwb3J0IGZvciBUaW9nYVBhc3MgUGxhdGZvcm0gYW5kIE92ZXJy aWRlIGdlbmVyaWMgUGNpQnVzIERyaXZlciB3aXRoDQoNCg0KQWRkIEJvYXJkVGlvZ2FQYXNzIHBh Y2thZ2VzIHRvIHN1cHBvcnQgVGlvZ2FQYXNzIFBsYXRmb3JtIEVuYWJsZWQgTmV0d29yaywgSVND U0ksSVBNSSwgU01CSU9TLCBQZXJmb3JtYW5jZSBNZWFzdXJlbWVudA0KUmVtb3ZlIEFTVDI1MDAg VUVGSSBvcHRpb24gUk9NIGRyaXZlciBmcm9tIFB1cmxleU9wZW5Cb2FyZFBrZw0KDQpBU1QyNTAw IFVFRkkgb3B0aW9uIFJPTSBtb3ZlIHRvIGVkazItbm9uLW9zaSBBU3BlZWRHb3BCaW5Qa2cgVXBk YXRlIGNvcHlyaWdodCBoZWFkZXJzDQoNCg0KDQptYW5pY2thdmFzYWthbSBrYXJwYWdhdmluYXlh Z2FtICgyKToNCg0KICBQdXJsZXlPcGVuQm9hcmRQa2cgOiBTdXBwb3J0IGZvciBUaW9nYVBhc3Mg UGxhdGZvcm0NCg0KICBQdXJsZXlPcGVuQm9hcmRQa2cgOiBPdmVycmlkZSBnZW5lcmljIFBjaUJ1 cyBEcml2ZXIgd2l0aCBQbGF0Zm9ybQ0KDQogICAgc3BlY2lmaWMgaW5zdGFuY2Ugb2YgUGNpQnVz IGRyaXZlci4NCg0KDQoNCi4uLi9JcG1pRmVhdHVyZVBrZy9HZW5lcmljSXBtaS9EeGUvSXBtaUlu aXQuYyB8ICAgIDggKy0NCg0KLi4uL0FjcGkvQm9hcmRBY3BpRHhlL0FtbE9mZnNldFRhYmxlLmMg ICAgICAgIHwgIDQ1MyArLQ0KDQouLi4vQWNwaS9Cb2FyZEFjcGlEeGUvQm9hcmRBY3BpRHhlRHNk dC5jICAgICAgfCAgICAzICsNCg0KLi4uL0JvYXJkVGlvZ2FQYXNzL0NvcmVEeGVJbmNsdWRlLmRz YyAgICAgICAgIHwgIDE2OCArDQoNCi4uLi9Cb2FyZFRpb2dhUGFzcy9Db3JlVWVmaUJvb3RJbmNs dWRlLmZkZiAgICB8ICAgODIgKw0KDQouLi4vQm9hcmRUaW9nYVBhc3MvR2l0RWRrMk1pblRpb2dh UGFzcy5iYXQgICAgfCAgIDkzICsNCg0KLi4uL0Jhc2VQbGF0Zm9ybUhvb2tMaWIvQmFzZVBsYXRm b3JtSG9va0xpYi5jIHwgIDM4OSArDQoNCi4uLi9CYXNlUGxhdGZvcm1Ib29rTGliLmluZiAgICAg ICAgICAgICAgICAgICB8ICAgMzYgKw0KDQouLi4vQm9hcmRBY3BpTGliL0R4ZUJvYXJkQWNwaVRh YmxlTGliLmMgICAgICAgfCAgIDM2ICsNCg0KLi4uL0JvYXJkQWNwaUxpYi9EeGVCb2FyZEFjcGlU YWJsZUxpYi5pbmYgICAgIHwgICA0MCArDQoNCi4uLi9Cb2FyZEFjcGlMaWIvRHhlVGlvZ2FQYXNz QWNwaVRhYmxlTGliLmMgICB8ICAgNTMgKw0KDQouLi4vQm9hcmRBY3BpTGliL1NtbUJvYXJkQWNw aUVuYWJsZUxpYi5jICAgICAgfCAgIDYyICsNCg0KLi4uL0JvYXJkQWNwaUxpYi9TbW1Cb2FyZEFj cGlFbmFibGVMaWIuaW5mICAgIHwgICA0MSArDQoNCi4uLi9Cb2FyZEFjcGlMaWIvU21tU2lsaWNv bkFjcGlFbmFibGVMaWIuYyAgICB8ICAxMjAgKw0KDQouLi4vQm9hcmRBY3BpTGliL1NtbVRpb2dh UGFzc0FjcGlFbmFibGVMaWIuYyAgfCAgIDM3ICsNCg0KLi4uL0xpYnJhcnkvQm9hcmRJbml0TGli L0FsbExhbmVzRXBhcmFtLmMgICAgIHwgICA0NCArDQoNCi4uLi9MaWJyYXJ5L0JvYXJkSW5pdExp Yi9HcGlvVGFibGUuYyAgICAgICAgICB8ICAyOTYgKw0KDQouLi4vTGlicmFyeS9Cb2FyZEluaXRM aWIvSWlvQmlmdXIuYyAgICAgICAgICAgfCAgIDcwICsNCg0KLi4uL0JvYXJkSW5pdExpYi9QZWlC b2FyZEluaXRQb3N0TWVtTGliLmMgICAgIHwgICA0NiArDQoNCi4uLi9Cb2FyZEluaXRMaWIvUGVp Qm9hcmRJbml0UG9zdE1lbUxpYi5pbmYgICB8ICAgMzcgKw0KDQouLi4vQm9hcmRJbml0TGliL1Bl aUJvYXJkSW5pdFByZU1lbUxpYi5jICAgICAgfCAgMTEyICsNCg0KLi4uL0JvYXJkSW5pdExpYi9Q ZWlCb2FyZEluaXRQcmVNZW1MaWIuaW5mICAgIHwgICA2OSArDQoNCi4uLi9MaWJyYXJ5L0JvYXJk SW5pdExpYi9QZWlUaW9nYVBhc3NEZXRlY3QuYyB8ICAgMjggKw0KDQouLi4vQm9hcmRJbml0TGli L1BlaVRpb2dhUGFzc0luaXRMaWIuaCAgICAgICAgfCAgIDE4ICsNCg0KLi4uL0JvYXJkSW5pdExp Yi9QZWlUaW9nYVBhc3NJbml0UG9zdE1lbUxpYi5jIHwgICA4NiArDQoNCi4uLi9Cb2FyZEluaXRM aWIvUGVpVGlvZ2FQYXNzSW5pdFByZU1lbUxpYi5jICB8ICA2MzggKysNCg0KLi4uL0xpYnJhcnkv Qm9hcmRJbml0TGliL1VzYk9DLmMgICAgICAgICAgICAgIHwgICA0NiArDQoNCi4uLi9MaWJyYXJ5 L1BlaVJlcG9ydEZ2TGliL1BlaVJlcG9ydEZ2TGliLmMgICB8ICAxMzggKw0KDQouLi4vTGlicmFy eS9QZWlSZXBvcnRGdkxpYi9QZWlSZXBvcnRGdkxpYi5pbmYgfCAgIDUxICsNCg0KLi4uL0JvYXJk VGlvZ2FQYXNzL09wZW5Cb2FyZFBrZy5kc2MgICAgICAgICAgIHwgIDI0NSArDQoNCi4uLi9Cb2Fy ZFRpb2dhUGFzcy9PcGVuQm9hcmRQa2cuZmRmICAgICAgICAgICB8ICA2MDAgKysNCg0KLi4uL0Jv YXJkVGlvZ2FQYXNzL1BsYXRmb3JtUGtnQnVpbGRPcHRpb24uZHNjIHwgICA4NCArDQoNCi4uLi9C b2FyZFRpb2dhUGFzcy9QbGF0Zm9ybVBrZ0NvbmZpZy5kc2MgICAgICB8ICAgNTggKw0KDQouLi4v Qm9hcmRUaW9nYVBhc3MvUGxhdGZvcm1Qa2dQY2QuZHNjICAgICAgICAgfCAgMzkyICsrDQoNCi4u Li9Cb2FyZFRpb2dhUGFzcy9TdHJ1Y3R1cmVDb25maWcuZHNjICAgICAgICB8IDYyMzYgKysrKysr KysrKysrKysrKysNCg0KLi4uL0JvYXJkVGlvZ2FQYXNzL19faW5pdF9fLnB5ICAgICAgICAgICAg ICAgIHwgICAgMA0KDQouLi4vUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL2JsZC5i YXQgfCAgMTM5ICsNCg0KLi4uL0JvYXJkVGlvZ2FQYXNzL2J1aWxkX2JvYXJkLnB5ICAgICAgICAg ICAgIHwgIDE5NSArDQoNCi4uLi9Cb2FyZFRpb2dhUGFzcy9idWlsZF9jb25maWcuY2ZnICAgICAg ICAgICB8ICAgMzQgKw0KDQouLi4vQm9hcmRUaW9nYVBhc3MvbG9nby50eHQgICAgICAgICAgICAg ICAgICAgfCAgIDEwICsNCg0KLi4uL0JvYXJkVGlvZ2FQYXNzL3Bvc3RidWlsZC5iYXQgICAgICAg ICAgICAgIHwgICA5NiArDQoNCi4uLi9Cb2FyZFRpb2dhUGFzcy9wcmVidWlsZC5iYXQgICAgICAg ICAgICAgICB8ICAyMTMgKw0KDQouLi4vSXBtaS9MaWJyYXJ5L0lwbWlMaWJLY3MvSXBtaUxpYktj cy5pbmYgICAgfCAgIDEwICstDQoNCi4uLi9JcG1pUGxhdGZvcm1Ib29rTGliLmluZiAgICAgICAg ICAgICAgICAgICB8ICAgIDYgKy0NCg0KLi4uL0luY2x1ZGUvR3VpZC9QY2hSY1ZhcmlhYmxlLmgg ICAgICAgICAgICAgIHwgICAgNiArDQoNCi4uLi9JbmNsdWRlL0d1aWQvU2V0dXBWYXJpYWJsZS5o ICAgICAgICAgICAgICB8ICAgMTUgKy0NCg0KLi4uL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9P cGVuQm9hcmRQa2cuZGVjIHwgICAgMSArDQoNCi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9Db21wb25l bnROYW1lLmMgICAgICAgICB8ICAxNzAgKw0KDQouLi4vQnVzL1BjaS9QY2lCdXNEeGUvQ29tcG9u ZW50TmFtZS5oICAgICAgICAgfCAgMTQ2ICsNCg0KLi4uL01kZU1vZHVsZVBrZy9CdXMvUGNpL1Bj aUJ1c0R4ZS9QY2lCdXMuYyAgIHwgIDQ2MCArKw0KDQouLi4vTWRlTW9kdWxlUGtnL0J1cy9QY2kv UGNpQnVzRHhlL1BjaUJ1cy5oICAgfCAgMzk2ICsrDQoNCi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9Q Y2lCdXNEeGUuaW5mICAgICAgICAgICB8ICAxMTIgKw0KDQouLi4vQnVzL1BjaS9QY2lCdXNEeGUv UGNpQnVzRHhlLnVuaSAgICAgICAgICAgfCAgIDE2ICsNCg0KLi4uL0J1cy9QY2kvUGNpQnVzRHhl L1BjaUJ1c0R4ZUV4dHJhLnVuaSAgICAgIHwgICAxNCArDQoNCi4uLi9CdXMvUGNpL1BjaUJ1c0R4 ZS9QY2lDb21tYW5kLmMgICAgICAgICAgICB8ICAyNjcgKw0KDQouLi4vQnVzL1BjaS9QY2lCdXNE eGUvUGNpQ29tbWFuZC5oICAgICAgICAgICAgfCAgMjMyICsNCg0KLi4uL0J1cy9QY2kvUGNpQnVz RHhlL1BjaURldmljZVN1cHBvcnQuYyAgICAgIHwgMTA1NiArKysNCg0KLi4uL0J1cy9QY2kvUGNp QnVzRHhlL1BjaURldmljZVN1cHBvcnQuaCAgICAgIHwgIDI2NiArDQoNCi4uLi9CdXMvUGNpL1Bj aUJ1c0R4ZS9QY2lEcml2ZXJPdmVycmlkZS5jICAgICB8ICAxODggKw0KDQouLi4vQnVzL1BjaS9Q Y2lCdXNEeGUvUGNpRHJpdmVyT3ZlcnJpZGUuaCAgICAgfCAgIDgzICsNCg0KLi4uL0J1cy9QY2kv UGNpQnVzRHhlL1BjaUVudW1lcmF0b3IuYyAgICAgICAgIHwgMjIxMCArKysrKysNCg0KLi4uL0J1 cy9QY2kvUGNpQnVzRHhlL1BjaUVudW1lcmF0b3IuaCAgICAgICAgIHwgIDUxNSArKw0KDQouLi4v QnVzL1BjaS9QY2lCdXNEeGUvUGNpRW51bWVyYXRvclN1cHBvcnQuYyAgfCAyODg1ICsrKysrKysr ICAuLi4vQnVzL1BjaS9QY2lCdXNEeGUvUGNpRW51bWVyYXRvclN1cHBvcnQuaCAgfCAgNDgwICsr DQoNCi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lIb3RQbHVnU3VwcG9ydC5jICAgICB8ICA0ODQg KysNCg0KLi4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUhvdFBsdWdTdXBwb3J0LmggICAgIHwgIDIw NSArDQoNCi4uLi9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpSW8uYyAgICB8IDIw ODcgKysrKysrDQoNCi4uLi9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpSW8uaCAg ICB8ICA2NjAgKysNCg0KLi4uL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lMaWIu YyAgIHwgMTgwOSArKysrKw0KDQouLi4vTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1Bj aUxpYi5oICAgfCAgMTc5ICsNCg0KLi4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaU9wdGlvblJvbVN1 cHBvcnQuYyAgIHwgIDc3NiArKw0KDQouLi4vQnVzL1BjaS9QY2lCdXNEeGUvUGNpT3B0aW9uUm9t U3VwcG9ydC5oICAgfCAgMTM2ICsNCg0KLi4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaVBvd2VyTWFu YWdlbWVudC5jICAgIHwgICA4MiArDQoNCi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lQb3dlck1h bmFnZW1lbnQuaCAgICB8ICAgMjggKw0KDQouLi4vQnVzL1BjaS9QY2lCdXNEeGUvUGNpUmVzb3Vy Y2VTdXBwb3J0LmMgICAgfCAyMjkyICsrKysrKw0KDQouLi4vQnVzL1BjaS9QY2lCdXNEeGUvUGNp UmVzb3VyY2VTdXBwb3J0LmggICAgfCAgNDU2ICsrDQoNCi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9Q Y2lSb21UYWJsZS5jICAgICAgICAgICB8ICAxMzUgKw0KDQouLi4vQnVzL1BjaS9QY2lCdXNEeGUv UGNpUm9tVGFibGUuaCAgICAgICAgICAgfCAgIDQ4ICsNCg0KUGxhdGZvcm0vSW50ZWwvYnVpbGQu Y2ZnICAgICAgICAgICAgICAgICAgICAgIHwgICAgMiArDQoNClBsYXRmb3JtL0ludGVsL2J1aWxk X2Jpb3MucHkgICAgICAgICAgICAgICAgICB8ICAgIDMgKy0NCg0KODAgZmlsZXMgY2hhbmdlZCwg MzAyNzggaW5zZXJ0aW9ucygrKSwgMjQwIGRlbGV0aW9ucygtKSAgY3JlYXRlIG1vZGUgMTAwNjQ0 IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9Db3JlRHhl SW5jbHVkZS5kc2MNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9w ZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9Db3JlVWVmaUJvb3RJbmNsdWRlLmZkZg0KDQpjcmVh dGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlv Z2FQYXNzL0dpdEVkazJNaW5UaW9nYVBhc3MuYmF0DQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0 Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3MvTGlicmFyeS9CYXNl UGxhdGZvcm1Ib29rTGliL0Jhc2VQbGF0Zm9ybUhvb2tMaWIuYw0KDQpjcmVhdGUgbW9kZSAxMDA2 NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xpYnJh cnkvQmFzZVBsYXRmb3JtSG9va0xpYi9CYXNlUGxhdGZvcm1Ib29rTGliLmluZg0KDQpjcmVhdGUg bW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQ YXNzL0xpYnJhcnkvQm9hcmRBY3BpTGliL0R4ZUJvYXJkQWNwaVRhYmxlTGliLmMNCg0KY3JlYXRl IG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dh UGFzcy9MaWJyYXJ5L0JvYXJkQWNwaUxpYi9EeGVCb2FyZEFjcGlUYWJsZUxpYi5pbmYNCg0KY3Jl YXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRp b2dhUGFzcy9MaWJyYXJ5L0JvYXJkQWNwaUxpYi9EeGVUaW9nYVBhc3NBY3BpVGFibGVMaWIuYw0K DQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0Jv YXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRBY3BpTGliL1NtbUJvYXJkQWNwaUVuYWJsZUxpYi5j DQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cv Qm9hcmRUaW9nYVBhc3MvTGlicmFyeS9Cb2FyZEFjcGlMaWIvU21tQm9hcmRBY3BpRW5hYmxlTGli LmluZg0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJk UGtnL0JvYXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRBY3BpTGliL1NtbVNpbGljb25BY3BpRW5h YmxlTGliLmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5C b2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkQWNwaUxpYi9TbW1UaW9nYVBhc3NB Y3BpRW5hYmxlTGliLmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxl eU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9BbGxMYW5l c0VwYXJhbS5jDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVu Qm9hcmRQa2cvQm9hcmRUaW9nYVBhc3MvTGlicmFyeS9Cb2FyZEluaXRMaWIvR3Bpb1RhYmxlLmMN Cg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9C b2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9JaW9CaWZ1ci5jDQoNCmNyZWF0ZSBt b2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBh c3MvTGlicmFyeS9Cb2FyZEluaXRMaWIvUGVpQm9hcmRJbml0UG9zdE1lbUxpYi5jDQoNCmNyZWF0 ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9n YVBhc3MvTGlicmFyeS9Cb2FyZEluaXRMaWIvUGVpQm9hcmRJbml0UG9zdE1lbUxpYi5pbmYNCg0K Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2Fy ZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9QZWlCb2FyZEluaXRQcmVNZW1MaWIuYw0K DQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0Jv YXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRJbml0TGliL1BlaUJvYXJkSW5pdFByZU1lbUxpYi5p bmYNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBr Zy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9QZWlUaW9nYVBhc3NEZXRlY3Qu Yw0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtn L0JvYXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRJbml0TGliL1BlaVRpb2dhUGFzc0luaXRMaWIu aA0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtn L0JvYXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRJbml0TGliL1BlaVRpb2dhUGFzc0luaXRQb3N0 TWVtTGliLmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5C b2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9QZWlUaW9nYVBhc3NJ bml0UHJlTWVtTGliLmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxl eU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9Vc2JPQy5j DQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cv Qm9hcmRUaW9nYVBhc3MvTGlicmFyeS9QZWlSZXBvcnRGdkxpYi9QZWlSZXBvcnRGdkxpYi5jDQoN CmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9h cmRUaW9nYVBhc3MvTGlicmFyeS9QZWlSZXBvcnRGdkxpYi9QZWlSZXBvcnRGdkxpYi5pbmYNCg0K Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2Fy ZFRpb2dhUGFzcy9PcGVuQm9hcmRQa2cuZHNjDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9y bS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3MvT3BlbkJvYXJkUGtnLmZk Zg0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtn L0JvYXJkVGlvZ2FQYXNzL1BsYXRmb3JtUGtnQnVpbGRPcHRpb24uZHNjDQoNCmNyZWF0ZSBtb2Rl IDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3Mv UGxhdGZvcm1Qa2dDb25maWcuZHNjDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRl bC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3MvUGxhdGZvcm1Qa2dQY2QuZHNjDQoN CmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9h cmRUaW9nYVBhc3MvU3RydWN0dXJlQ29uZmlnLmRzYw0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxh dGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL19faW5pdF9fLnB5 DQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cv Qm9hcmRUaW9nYVBhc3MvYmxkLmJhdA0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50 ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL2J1aWxkX2JvYXJkLnB5DQoNCmNy ZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRU aW9nYVBhc3MvYnVpbGRfY29uZmlnLmNmZw0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0v SW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL2xvZ28udHh0DQoNCmNyZWF0 ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9n YVBhc3MvcG9zdGJ1aWxkLmJhdA0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwv UHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL3ByZWJ1aWxkLmJhdA0KDQpjcmVhdGUg bW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01k ZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9Db21wb25lbnROYW1lLmMNCg0KY3JlYXRlIG1v ZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVN b2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvQ29tcG9uZW50TmFtZS5oDQoNCmNyZWF0ZSBtb2Rl IDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9k dWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUJ1cy5jDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQ bGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1 cy9QY2kvUGNpQnVzRHhlL1BjaUJ1cy5oDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9J bnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNp QnVzRHhlL1BjaUJ1c0R4ZS5pbmYNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVs L1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNE eGUvUGNpQnVzRHhlLnVuaQ0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVy bGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9Q Y2lCdXNEeGVFeHRyYS51bmkNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1 cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUv UGNpQ29tbWFuZC5jDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlP cGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUNv bW1hbmQuaA0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJv YXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lEZXZpY2VT dXBwb3J0LmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5C b2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpRGV2aWNl U3VwcG9ydC5oDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVu Qm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaURyaXZl ck92ZXJyaWRlLmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9w ZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpRHJp dmVyT3ZlcnJpZGUuaA0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5 T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lF bnVtZXJhdG9yLmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9w ZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpRW51 bWVyYXRvci5oDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVu Qm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUVudW1l cmF0b3JTdXBwb3J0LmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxl eU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNp RW51bWVyYXRvclN1cHBvcnQuaA0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwv UHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4 ZS9QY2lIb3RQbHVnU3VwcG9ydC5jDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRl bC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVz RHhlL1BjaUhvdFBsdWdTdXBwb3J0LmgNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0lu dGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lC dXNEeGUvUGNpSW8uYw0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5 T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lJ by5oDQoNCmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQ a2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUxpYi5jDQoNCmNy ZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJp ZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUxpYi5oDQoNCmNyZWF0ZSBtb2Rl IDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9k dWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaU9wdGlvblJvbVN1cHBvcnQuYw0KDQpjcmVhdGUg bW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01k ZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lPcHRpb25Sb21TdXBwb3J0LmgNCg0KY3Jl YXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlk ZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpUG93ZXJNYW5hZ2VtZW50LmMNCg0K Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVy cmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpUG93ZXJNYW5hZ2VtZW50LmgN Cg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9P dmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpUmVzb3VyY2VTdXBwb3J0 LmMNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBr Zy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpUmVzb3VyY2VTdXBw b3J0LmgNCg0KY3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2Fy ZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpUm9tVGFibGUu Yw0KDQpjcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtn L092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lSb21UYWJsZS5oDQoN Ci1UaGUgaW5mb3JtYXRpb24gY29udGFpbmVkIGluIHRoaXMgbWVzc2FnZSBtYXkgYmUgY29uZmlk ZW50aWFsIGFuZCBwcm9wcmlldGFyeSB0byBBbWVyaWNhbiBNZWdhdHJlbmRzIChBTUkpLiBUaGlz IGNvbW11bmljYXRpb24gaXMgaW50ZW5kZWQgdG8gYmUgcmVhZCBvbmx5IGJ5IHRoZSBpbmRpdmlk dWFsIG9yIGVudGl0eSB0byB3aG9tIGl0IGlzIGFkZHJlc3NlZCBvciBieSB0aGVpciBkZXNpZ25l ZS4gSWYgdGhlIHJlYWRlciBvZiB0aGlzIG1lc3NhZ2UgaXMgbm90IHRoZSBpbnRlbmRlZCByZWNp cGllbnQsIHlvdSBhcmUgb24gbm90aWNlIHRoYXQgYW55IGRpc3RyaWJ1dGlvbiBvZiB0aGlzIG1l c3NhZ2UsIGluIGFueSBmb3JtLCBpcyBzdHJpY3RseSBwcm9oaWJpdGVkLiBQbGVhc2UgcHJvbXB0 bHkgbm90aWZ5IHRoZSBzZW5kZXIgYnkgcmVwbHkgZS1tYWlsIG9yIGJ5IHRlbGVwaG9uZSBhdCA3 NzAtMjQ2LTg2MDAsIGFuZCB0aGVuIGRlbGV0ZSBvciBkZXN0cm95IGFsbCBjb3BpZXMgb2YgdGhl IHRyYW5zbWlzc2lvbi4NCg== --_000_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_ Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: base64 PGh0bWwgeG1sbnM6dj0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwiIHhtbG5zOm89InVy bjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9mZmljZSIgeG1sbnM6dz0idXJuOnNjaGVt YXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6d29yZCIgeG1sbnM6bT0iaHR0cDovL3NjaGVtYXMubWlj cm9zb2Z0LmNvbS9vZmZpY2UvMjAwNC8xMi9vbW1sIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv VFIvUkVDLWh0bWw0MCI+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIg Y29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjxtZXRhIG5hbWU9IkdlbmVyYXRv ciIgY29udGVudD0iTWljcm9zb2Z0IFdvcmQgMTUgKGZpbHRlcmVkIG1lZGl1bSkiPg0KPCEtLVtp ZiAhbXNvXT48c3R5bGU+dlw6KiB7YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTCk7fQ0Kb1w6KiB7 YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTCk7fQ0Kd1w6KiB7YmVoYXZpb3I6dXJsKCNkZWZhdWx0 I1ZNTCk7fQ0KLnNoYXBlIHtiZWhhdmlvcjp1cmwoI2RlZmF1bHQjVk1MKTt9DQo8L3N0eWxlPjwh W2VuZGlmXS0tPjxzdHlsZT48IS0tDQovKiBGb250IERlZmluaXRpb25zICovDQpAZm9udC1mYWNl DQoJe2ZvbnQtZmFtaWx5OlNpbVN1bjsNCglwYW5vc2UtMToyIDEgNiAwIDMgMSAxIDEgMSAxO30N CkBmb250LWZhY2UNCgl7Zm9udC1mYW1pbHk6IkNhbWJyaWEgTWF0aCI7DQoJcGFub3NlLTE6MiA0 IDUgMyA1IDQgNiAzIDIgNDt9DQpAZm9udC1mYWNlDQoJe2ZvbnQtZmFtaWx5OkRlbmdYaWFuOw0K CXBhbm9zZS0xOjIgMSA2IDAgMyAxIDEgMSAxIDE7fQ0KQGZvbnQtZmFjZQ0KCXtmb250LWZhbWls eTpDYWxpYnJpOw0KCXBhbm9zZS0xOjIgMTUgNSAyIDIgMiA0IDMgMiA0O30NCkBmb250LWZhY2UN Cgl7Zm9udC1mYW1pbHk6VGFob21hOw0KCXBhbm9zZS0xOjIgMTEgNiA0IDMgNSA0IDQgMiA0O30N CkBmb250LWZhY2UNCgl7Zm9udC1mYW1pbHk6Q29uc29sYXM7DQoJcGFub3NlLTE6MiAxMSA2IDkg MiAyIDQgMyAyIDQ7fQ0KQGZvbnQtZmFjZQ0KCXtmb250LWZhbWlseToiXEBTaW1TdW4iOw0KCXBh bm9zZS0xOjIgMSA2IDAgMyAxIDEgMSAxIDE7fQ0KQGZvbnQtZmFjZQ0KCXtmb250LWZhbWlseToi XEBEZW5nWGlhbiI7DQoJcGFub3NlLTE6MiAxIDYgMCAzIDEgMSAxIDEgMTt9DQovKiBTdHlsZSBE ZWZpbml0aW9ucyAqLw0KcC5Nc29Ob3JtYWwsIGxpLk1zb05vcm1hbCwgZGl2Lk1zb05vcm1hbA0K CXttYXJnaW46MGluOw0KCWZvbnQtc2l6ZToxMi4wcHQ7DQoJZm9udC1mYW1pbHk6U2ltU3VuOw0K CW1zby1mYXJlYXN0LWxhbmd1YWdlOlpILUNOO30NCmE6bGluaywgc3Bhbi5Nc29IeXBlcmxpbmsN Cgl7bXNvLXN0eWxlLXByaW9yaXR5Ojk5Ow0KCWNvbG9yOmJsdWU7DQoJdGV4dC1kZWNvcmF0aW9u OnVuZGVybGluZTt9DQpwLk1zb1BsYWluVGV4dCwgbGkuTXNvUGxhaW5UZXh0LCBkaXYuTXNvUGxh aW5UZXh0DQoJe21zby1zdHlsZS1wcmlvcml0eTo5OTsNCgltc28tc3R5bGUtbGluazoiUGxhaW4g VGV4dCBDaGFyIjsNCgltc28tbWFyZ2luLXRvcC1hbHQ6YXV0bzsNCgltYXJnaW4tcmlnaHQ6MGlu Ow0KCW1zby1tYXJnaW4tYm90dG9tLWFsdDphdXRvOw0KCW1hcmdpbi1sZWZ0OjBpbjsNCglmb250 LXNpemU6MTIuMHB0Ow0KCWZvbnQtZmFtaWx5OlNpbVN1bjsNCgltc28tZmFyZWFzdC1sYW5ndWFn ZTpaSC1DTjt9DQpzcGFuLlBsYWluVGV4dENoYXINCgl7bXNvLXN0eWxlLW5hbWU6IlBsYWluIFRl eHQgQ2hhciI7DQoJbXNvLXN0eWxlLXByaW9yaXR5Ojk5Ow0KCW1zby1zdHlsZS1saW5rOiJQbGFp biBUZXh0IjsNCglmb250LWZhbWlseTpDb25zb2xhczsNCgltc28tZmFyZWFzdC1sYW5ndWFnZTpa SC1DTjt9DQpzcGFuLkVtYWlsU3R5bGUyNg0KCXttc28tc3R5bGUtdHlwZTpwZXJzb25hbC1yZXBs eTsNCglmb250LWZhbWlseToiVGFob21hIixzYW5zLXNlcmlmOw0KCWNvbG9yOndpbmRvd3RleHQ7 DQoJZm9udC13ZWlnaHQ6bm9ybWFsOw0KCWZvbnQtc3R5bGU6bm9ybWFsOw0KCXRleHQtZGVjb3Jh dGlvbjpub25lIG5vbmU7fQ0KLk1zb0NocERlZmF1bHQNCgl7bXNvLXN0eWxlLXR5cGU6ZXhwb3J0 LW9ubHk7DQoJZm9udC1zaXplOjEwLjBwdDt9DQpAcGFnZSBXb3JkU2VjdGlvbjENCgl7c2l6ZTo4 LjVpbiAxMS4waW47DQoJbWFyZ2luOjEuMGluIDEuMjVpbiAxLjBpbiAxLjI1aW47fQ0KZGl2Lldv cmRTZWN0aW9uMQ0KCXtwYWdlOldvcmRTZWN0aW9uMTt9DQotLT48L3N0eWxlPjwhLS1baWYgZ3Rl IG1zbyA5XT48eG1sPg0KPG86c2hhcGVkZWZhdWx0cyB2OmV4dD0iZWRpdCIgc3BpZG1heD0iMTAy NiIgLz4NCjwveG1sPjwhW2VuZGlmXS0tPjwhLS1baWYgZ3RlIG1zbyA5XT48eG1sPg0KPG86c2hh cGVsYXlvdXQgdjpleHQ9ImVkaXQiPg0KPG86aWRtYXAgdjpleHQ9ImVkaXQiIGRhdGE9IjEiIC8+ DQo8L286c2hhcGVsYXlvdXQ+PC94bWw+PCFbZW5kaWZdLS0+DQo8L2hlYWQ+DQo8Ym9keSBsYW5n PSJFTi1VUyIgbGluaz0iYmx1ZSIgdmxpbms9InB1cnBsZSIgc3R5bGU9IndvcmQtd3JhcDpicmVh ay13b3JkIj4NCjxkaXYgY2xhc3M9IldvcmRTZWN0aW9uMSI+DQo8cCBjbGFzcz0iTXNvTm9ybWFs Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEwLjBwdDtmb250LWZhbWlseTomcXVvdDtUYWhvbWEm cXVvdDssc2Fucy1zZXJpZjttc28tZmFyZWFzdC1sYW5ndWFnZTpFTi1VUyI+TGltaW5nIDo8bzpw PjwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBzdHlsZT0iZm9u dC1zaXplOjEwLjBwdDtmb250LWZhbWlseTomcXVvdDtUYWhvbWEmcXVvdDssc2Fucy1zZXJpZjtt c28tZmFyZWFzdC1sYW5ndWFnZTpFTi1VUyI+PG86cD4mbmJzcDs8L286cD48L3NwYW4+PC9wPg0K PHAgY2xhc3M9Ik1zb05vcm1hbCI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZToxMC4wcHQ7Zm9udC1m YW1pbHk6JnF1b3Q7VGFob21hJnF1b3Q7LHNhbnMtc2VyaWY7bXNvLWZhcmVhc3QtbGFuZ3VhZ2U6 RU4tVVMiPkJlbG93IGVtYWlsIGlzIHRoZSBjb3ZlciBsZXR0ZXIgYW5kIHRoaXMgcGF0Y2ggc2Vy aWVzIGhhcyB0d28gY2hhbmdlcy4gU3VyZSBuZXh0IHRpbWUsIHdpbGwgYWRkIG1vcmUgY29tbWVu dHMgaW4gdGhlIGNvdmVyIGxldHRlciBhbHNvLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNs YXNzPSJNc29Ob3JtYWwiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTAuMHB0O2ZvbnQtZmFtaWx5 OiZxdW90O1RhaG9tYSZxdW90OyxzYW5zLXNlcmlmO21zby1mYXJlYXN0LWxhbmd1YWdlOkVOLVVT Ij5QbGVhc2UgcmVmZXIgdGhlIGF0dGFjaGVkIGVtYWlsIGFuZCBpdCBoYXMgaW5mb3JtYXRpb24g YWJvdXQgdGhlIFBDSUJVUyBvdmVycmlkZSBjaGFuZ2VzLiBQQ0lCVVMgb3ZlcnJpZGUgaXMgZG9u ZSBiYXNlZCBvbiB0aGUgcGxhdGZvcm0gc2lnaHRpbmcgYW5kDQogaXQgY2Fu4oCZdCBiZSBnZW5l cmljLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxzcGFuIHN0 eWxlPSJmb250LXNpemU6MTAuMHB0O2ZvbnQtZmFtaWx5OiZxdW90O1RhaG9tYSZxdW90OyxzYW5z LXNlcmlmO21zby1mYXJlYXN0LWxhbmd1YWdlOkVOLVVTIj48bzpwPiZuYnNwOzwvbzpwPjwvc3Bh bj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEwLjBw dDtmb250LWZhbWlseTomcXVvdDtUYWhvbWEmcXVvdDssc2Fucy1zZXJpZjttc28tZmFyZWFzdC1s YW5ndWFnZTpFTi1VUyI+VGhhbmsgeW91PG86cD48L286cD48L3NwYW4+PC9wPg0KPHAgY2xhc3M9 Ik1zb05vcm1hbCI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZToxMC4wcHQ7Zm9udC1mYW1pbHk6JnF1 b3Q7VGFob21hJnF1b3Q7LHNhbnMtc2VyaWY7bXNvLWZhcmVhc3QtbGFuZ3VhZ2U6RU4tVVMiPjxv OnA+Jm5ic3A7PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxzcGFuIHN0 eWxlPSJmb250LXNpemU6MTAuMHB0O2ZvbnQtZmFtaWx5OiZxdW90O1RhaG9tYSZxdW90OyxzYW5z LXNlcmlmO21zby1mYXJlYXN0LWxhbmd1YWdlOkVOLVVTIj4tTWFuaWM8bzpwPjwvbzpwPjwvc3Bh bj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEwLjBw dDtmb250LWZhbWlseTomcXVvdDtUYWhvbWEmcXVvdDssc2Fucy1zZXJpZjttc28tZmFyZWFzdC1s YW5ndWFnZTpFTi1VUyI+PG86cD4mbmJzcDs8L286cD48L3NwYW4+PC9wPg0KPGRpdj4NCjxkaXYg c3R5bGU9ImJvcmRlcjpub25lO2JvcmRlci10b3A6c29saWQgI0UxRTFFMSAxLjBwdDtwYWRkaW5n OjMuMHB0IDBpbiAwaW4gMGluIj4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxiPjxzcGFuIHN0eWxl PSJmb250LXNpemU6MTEuMHB0O2ZvbnQtZmFtaWx5OiZxdW90O0NhbGlicmkmcXVvdDssc2Fucy1z ZXJpZiI+RnJvbTo8L3NwYW4+PC9iPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTEuMHB0O2ZvbnQt ZmFtaWx5OiZxdW90O0NhbGlicmkmcXVvdDssc2Fucy1zZXJpZiI+IGdhb2xpbWluZyAmbHQ7Z2Fv bGltaW5nQGJ5b3NvZnQuY29tLmNuJmd0Ow0KPGJyPg0KPGI+U2VudDo8L2I+IFdlZG5lc2RheSwg SnVuZSAxNiwgMjAyMSAxMDo1NiBQTTxicj4NCjxiPlRvOjwvYj4gZGV2ZWxAZWRrMi5ncm91cHMu aW87IE1hbmlja2F2YXNha2FtIEthcnBhZ2F2aW5heWFnYW0gJmx0O21hbmlja2F2YXNha2Fta0Bh bWkuY29tJmd0Ozxicj4NCjxiPlN1YmplY3Q6PC9iPiBbRVhURVJOQUxdIDwvc3Bhbj48c3BhbiBs YW5nPSJaSC1DTiIgc3R5bGU9ImZvbnQtc2l6ZToxMS4wcHQiPuWbnuWkjTwvc3Bhbj48c3BhbiBz dHlsZT0iZm9udC1zaXplOjExLjBwdDtmb250LWZhbWlseTomcXVvdDtDYWxpYnJpJnF1b3Q7LHNh bnMtc2VyaWYiPjogW2VkazItZGV2ZWxdIFtlZGsyLXBsYXRmb3Jtc10gW1BBVENIIFYxIDAvMl0g U3VwcG9ydCBmb3IgVGlvZ2FQYXNzIFBsYXRmb3JtIGFuZCBPdmVycmlkZSBnZW5lcmljIFBjaUJ1 cw0KIERyaXZlciB3aXRoPG86cD48L286cD48L3NwYW4+PC9wPg0KPC9kaXY+DQo8L2Rpdj4NCjxw IGNsYXNzPSJNc29Ob3JtYWwiPjxvOnA+Jm5ic3A7PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb05v cm1hbCI+PG86cD4mbmJzcDs8L286cD48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIiBzdHlsZT0i bGluZS1oZWlnaHQ6MTIuMHB0O2JhY2tncm91bmQ6I0UwMjIyMiI+PHN0cm9uZz48c3BhbiBzdHls ZT0iZm9udC1zaXplOjEwLjBwdDtmb250LWZhbWlseTomcXVvdDtDYWxpYnJpJnF1b3Q7LHNhbnMt c2VyaWY7Y29sb3I6d2hpdGUiPioqQ0FVVElPTjo8L3NwYW4+PC9zdHJvbmc+PHNwYW4gc3R5bGU9 ImZvbnQtc2l6ZToxMC4wcHQ7Y29sb3I6d2hpdGUiPiBUaGUgZS1tYWlsIGJlbG93IGlzIGZyb20g YW4gZXh0ZXJuYWwNCiBzb3VyY2UuIFBsZWFzZSBleGVyY2lzZSBjYXV0aW9uIGJlZm9yZSBvcGVu aW5nIGF0dGFjaG1lbnRzLCBjbGlja2luZyBsaW5rcywgb3IgZm9sbG93aW5nIGd1aWRhbmNlLioq DQo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8ZGl2Pg0KPHAgY2xhc3M9Ik1zb05vcm1hbCI+PHNw YW4gc3R5bGU9ImZvbnQtc2l6ZToxMC41cHQ7Zm9udC1mYW1pbHk6RGVuZ1hpYW4iPjxvOnA+Jm5i c3A7PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxzcGFuIHN0eWxlPSJm b250LXNpemU6MTAuNXB0O2ZvbnQtZmFtaWx5OkRlbmdYaWFuIj5QbGVhc2UgZm9sbG93DQo8YSBo cmVmPSJodHRwczovL25hbTEyLnNhZmVsaW5rcy5wcm90ZWN0aW9uLm91dGxvb2suY29tLz91cmw9 aHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGdGlhbm9jb3JlJTJGdGlhbm9jb3JlLmdpdGh1Yi5p byUyRndpa2klMkZDb21taXQtTWVzc2FnZS1Gb3JtYXQmYW1wO2RhdGE9MDQlN0MwMSU3Q21hbmlj a2F2YXNha2FtayU0MGFtaS5jb20lN0M0NzhkMzhmZjIzNmE0OTZiMWY4YTA4ZDkzMTNiNzhiNSU3 QzI3ZTk3ODU3ZTE1ZjQ4NmNiNThlODZjMmIzMDQwZjkzJTdDMSU3QzAlN0M2Mzc1OTQ5NTM3Nzkx NTE4NDElN0NVbmtub3duJTdDVFdGcGJHWnNiM2Q4ZXlKV0lqb2lNQzR3TGpBd01EQWlMQ0pRSWpv aVYybHVNeklpTENKQlRpSTZJazFoYVd3aUxDSlhWQ0k2TW4wJTNEJTdDMTAwMCZhbXA7c2RhdGE9 UmhQJTJCQnk2MnVueGpRYXV2emUwNlRqelJlcSUyRkpmVWdxNyUyQjlEUjBSOGtOWSUzRCZhbXA7 cmVzZXJ2ZWQ9MCI+DQpodHRwczovL2dpdGh1Yi5jb20vdGlhbm9jb3JlL3RpYW5vY29yZS5naXRo dWIuaW8vd2lraS9Db21taXQtTWVzc2FnZS1Gb3JtYXQ8L2E+IHRvIHVwZGF0ZSB0aGUgY29tbWl0 IG1lc3NhZ2UgZm9ybWF0LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNsYXNzPSJNc29Ob3Jt YWwiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTAuNXB0O2ZvbnQtZmFtaWx5OkRlbmdYaWFuIj48 bzpwPiZuYnNwOzwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48c3BhbiBz dHlsZT0iZm9udC1zaXplOjEwLjVwdDtmb250LWZhbWlseTpEZW5nWGlhbiI+QW5kLCBmb3IgdGhl IG92ZXJyaWRlIFBjaUJ1cyBtb2R1bGUsIGNhbiB5b3UgZ2l2ZSBtb3JlIGRldGFpbCB3aHkgbmVl ZCB0byBvdmVycmlkZSBQY2lCdXM/IElzIGl0IHBvc3NpYmxlIHRvIHVwZGF0ZSBFZGsyIE1kZU1v ZHVsZVBrZyBQY2lCdXMgdG8gbWVldCB0aGUgcGxhdGZvcm0gcmVxdWlyZW1lbnQ/PG86cD48L286 cD48L3NwYW4+PC9wPg0KPHAgY2xhc3M9Ik1zb05vcm1hbCI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6 ZToxMC41cHQ7Zm9udC1mYW1pbHk6RGVuZ1hpYW4iPjxvOnA+Jm5ic3A7PC9vOnA+PC9zcGFuPjwv cD4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTAuNXB0O2Zv bnQtZmFtaWx5OkRlbmdYaWFuIj5UaGFua3M8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFz cz0iTXNvTm9ybWFsIj48c3BhbiBzdHlsZT0iZm9udC1zaXplOjEwLjVwdDtmb250LWZhbWlseTpE ZW5nWGlhbiI+TGltaW5nPG86cD48L286cD48L3NwYW4+PC9wPg0KPGRpdiBzdHlsZT0iYm9yZGVy Om5vbmU7Ym9yZGVyLWxlZnQ6c29saWQgYmx1ZSAxLjVwdDtwYWRkaW5nOjBpbiAwaW4gMGluIDQu MHB0Ij4NCjxkaXY+DQo8ZGl2IHN0eWxlPSJib3JkZXI6bm9uZTtib3JkZXItdG9wOnNvbGlkICNF MUUxRTEgMS4wcHQ7cGFkZGluZzozLjBwdCAwaW4gMGluIDBpbiI+DQo8cCBjbGFzcz0iTXNvTm9y bWFsIj48Yj48c3BhbiBsYW5nPSJaSC1DTiIgc3R5bGU9ImZvbnQtc2l6ZToxMS4wcHQ7Zm9udC1m YW1pbHk6RGVuZ1hpYW4iPuWPkeS7tuS6ujwvc3Bhbj48L2I+PGI+PHNwYW4gc3R5bGU9ImZvbnQt c2l6ZToxMS4wcHQ7Zm9udC1mYW1pbHk6RGVuZ1hpYW4iPjo8L3NwYW4+PC9iPjxzcGFuIHN0eWxl PSJmb250LXNpemU6MTEuMHB0O2ZvbnQtZmFtaWx5OkRlbmdYaWFuIj4NCjxhIGhyZWY9Im1haWx0 bzpkZXZlbEBlZGsyLmdyb3Vwcy5pbyI+ZGV2ZWxAZWRrMi5ncm91cHMuaW88L2E+ICZsdDs8YSBo cmVmPSJtYWlsdG86ZGV2ZWxAZWRrMi5ncm91cHMuaW8iPmRldmVsQGVkazIuZ3JvdXBzLmlvPC9h PiZndDsNCjxiPjxzcGFuIGxhbmc9IlpILUNOIj7ku6PooaggPC9zcGFuPjwvYj5tYW5pY2thdmFz YWthbSBrYXJwYWdhdmluYXlhZ2FtPGJyPg0KPGI+PHNwYW4gbGFuZz0iWkgtQ04iPuWPkemAgeaX tumXtDwvc3Bhbj46PC9iPiAyMDIxPHNwYW4gbGFuZz0iWkgtQ04iPuW5tDwvc3Bhbj42PHNwYW4g bGFuZz0iWkgtQ04iPuaciDwvc3Bhbj4xNzxzcGFuIGxhbmc9IlpILUNOIj7ml6U8L3NwYW4+IDc6 MDU8YnI+DQo8Yj48c3BhbiBsYW5nPSJaSC1DTiI+5pS25Lu25Lq6PC9zcGFuPjo8L2I+IDxhIGhy ZWY9Im1haWx0bzpkZXZlbEBlZGsyLmdyb3Vwcy5pbyI+ZGV2ZWxAZWRrMi5ncm91cHMuaW88L2E+ PGJyPg0KPGI+PHNwYW4gbGFuZz0iWkgtQ04iPuS4u+mimDwvc3Bhbj46PC9iPiBbZWRrMi1kZXZl bF0gW2VkazItcGxhdGZvcm1zXSBbUEFUQ0ggVjEgMC8yXSBTdXBwb3J0IGZvciBUaW9nYVBhc3Mg UGxhdGZvcm0gYW5kIE92ZXJyaWRlIGdlbmVyaWMgUGNpQnVzIERyaXZlciB3aXRoPG86cD48L286 cD48L3NwYW4+PC9wPg0KPC9kaXY+DQo8L2Rpdj4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxvOnA+ Jm5ic3A7PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+QWRkIEJvYXJkVGlvZ2FQ YXNzIHBhY2thZ2VzIHRvIHN1cHBvcnQgVGlvZ2FQYXNzIFBsYXRmb3JtIEVuYWJsZWQgTmV0d29y aywgSVNDU0ksSVBNSSwgU01CSU9TLCBQZXJmb3JtYW5jZSBNZWFzdXJlbWVudA0KPGJyPg0KUmVt b3ZlIEFTVDI1MDAgVUVGSSBvcHRpb24gUk9NIGRyaXZlciBmcm9tIFB1cmxleU9wZW5Cb2FyZFBr ZzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+QVNUMjUwMCBVRUZJIG9w dGlvbiBST00gbW92ZSB0byBlZGsyLW5vbi1vc2kgQVNwZWVkR29wQmluUGtnIFVwZGF0ZSBjb3B5 cmlnaHQgaGVhZGVyczxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Jm5i c3A7PG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5tYW5pY2thdmFzYWth bSBrYXJwYWdhdmluYXlhZ2FtICgyKTo8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFp blRleHQiPiZuYnNwOyBQdXJsZXlPcGVuQm9hcmRQa2cgOiBTdXBwb3J0IGZvciBUaW9nYVBhc3Mg UGxhdGZvcm08bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPiZuYnNwOyBQ dXJsZXlPcGVuQm9hcmRQa2cgOiBPdmVycmlkZSBnZW5lcmljIFBjaUJ1cyBEcml2ZXIgd2l0aCBQ bGF0Zm9ybTxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Jm5ic3A7Jm5i c3A7Jm5ic3A7IHNwZWNpZmljIGluc3RhbmNlIG9mIFBjaUJ1cyBkcml2ZXIuPG86cD48L286cD48 L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4mbmJzcDs8bzpwPjwvbzpwPjwvcD4NCjxwIGNs YXNzPSJNc29QbGFpblRleHQiPi4uLi9JcG1pRmVhdHVyZVBrZy9HZW5lcmljSXBtaS9EeGUvSXBt aUluaXQuYyB8Jm5ic3A7Jm5ic3A7Jm5ic3A7IDggKy08bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNz PSJNc29QbGFpblRleHQiPi4uLi9BY3BpL0JvYXJkQWNwaUR4ZS9BbWxPZmZzZXRUYWJsZS5jJm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsgNDUzICstPG86 cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQWNwaS9Cb2FyZEFjcGlE eGUvQm9hcmRBY3BpRHhlRHNkdC5jJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJz cDsmbmJzcDsmbmJzcDsgMyArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0 Ij4uLi4vQm9hcmRUaW9nYVBhc3MvQ29yZUR4ZUluY2x1ZGUuZHNjJm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsgMTY4ICs8bzpwPjwvbzpwPjwv cD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZFRpb2dhUGFzcy9Db3JlVWVmaUJv b3RJbmNsdWRlLmZkZiZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7Jm5ic3A7IDgyICs8bzpwPjwv bzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZFRpb2dhUGFzcy9HaXRF ZGsyTWluVGlvZ2FQYXNzLmJhdCZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7Jm5ic3A7IDkzICs8 bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9CYXNlUGxhdGZvcm1I b29rTGliL0Jhc2VQbGF0Zm9ybUhvb2tMaWIuYyB8Jm5ic3A7IDM4OSArPG86cD48L286cD48L3A+ DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQmFzZVBsYXRmb3JtSG9va0xpYi5pbmYmbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyZu YnNwOyAzNiArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQm9h cmRBY3BpTGliL0R4ZUJvYXJkQWNwaVRhYmxlTGliLmMmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyAzNiArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0i TXNvUGxhaW5UZXh0Ij4uLi4vQm9hcmRBY3BpTGliL0R4ZUJvYXJkQWNwaVRhYmxlTGliLmluZiZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7Jm5ic3A7IDQwICs8bzpwPjwvbzpwPjwvcD4N CjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZEFjcGlMaWIvRHhlVGlvZ2FQYXNzQWNw aVRhYmxlTGliLmMmbmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyA1MyArPG86cD48L286cD48L3A+ DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQm9hcmRBY3BpTGliL1NtbUJvYXJkQWNwaUVu YWJsZUxpYi5jJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJzcDsgNjIg KzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0JvYXJkQWNwaUxp Yi9TbW1Cb2FyZEFjcGlFbmFibGVMaWIuaW5mJm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJz cDsgNDEgKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0JvYXJk QWNwaUxpYi9TbW1TaWxpY29uQWNwaUVuYWJsZUxpYi5jJm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJz cDsgMTIwICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2Fy ZEFjcGlMaWIvU21tVGlvZ2FQYXNzQWNwaUVuYWJsZUxpYi5jJm5ic3A7IHwmbmJzcDsmbmJzcDsg MzcgKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0xpYnJhcnkv Qm9hcmRJbml0TGliL0FsbExhbmVzRXBhcmFtLmMmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZu YnNwOyZuYnNwOyA0NCArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4u Li4vTGlicmFyeS9Cb2FyZEluaXRMaWIvR3Bpb1RhYmxlLmMmbmJzcDsmbmJzcDsmbmJzcDsmbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyAyOTYgKzxvOnA+PC9vOnA+ PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0xpYnJhcnkvQm9hcmRJbml0TGliL0lp b0JpZnVyLmMmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyA3MCArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0i TXNvUGxhaW5UZXh0Ij4uLi4vQm9hcmRJbml0TGliL1BlaUJvYXJkSW5pdFBvc3RNZW1MaWIuYyZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7Jm5ic3A7IDQ2ICs8bzpwPjwvbzpwPjwvcD4N CjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZEluaXRMaWIvUGVpQm9hcmRJbml0UG9z dE1lbUxpYi5pbmYmbmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyAzNyArPG86cD48L286cD48L3A+ DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQm9hcmRJbml0TGliL1BlaUJvYXJkSW5pdFBy ZU1lbUxpYi5jJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsgMTEyICs8bzpw PjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZEluaXRMaWIvUGVp Qm9hcmRJbml0UHJlTWVtTGliLmluZiZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7Jm5ic3A7IDY5 ICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9MaWJyYXJ5L0Jv YXJkSW5pdExpYi9QZWlUaW9nYVBhc3NEZXRlY3QuYyB8Jm5ic3A7Jm5ic3A7IDI4ICs8bzpwPjwv bzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZEluaXRMaWIvUGVpVGlv Z2FQYXNzSW5pdExpYi5oJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7 IHwmbmJzcDsmbmJzcDsgMTggKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4 dCI+Li4uL0JvYXJkSW5pdExpYi9QZWlUaW9nYVBhc3NJbml0UG9zdE1lbUxpYi5jIHwmbmJzcDsm bmJzcDsgODYgKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0Jv YXJkSW5pdExpYi9QZWlUaW9nYVBhc3NJbml0UHJlTWVtTGliLmMmbmJzcDsgfCZuYnNwOyA2Mzgg Kys8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9MaWJyYXJ5L0Jv YXJkSW5pdExpYi9Vc2JPQy5jJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJzcDsgNDYg KzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0xpYnJhcnkvUGVp UmVwb3J0RnZMaWIvUGVpUmVwb3J0RnZMaWIuYyZuYnNwOyZuYnNwOyB8Jm5ic3A7IDEzOCArPG86 cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vTGlicmFyeS9QZWlSZXBv cnRGdkxpYi9QZWlSZXBvcnRGdkxpYi5pbmYgfCZuYnNwOyZuYnNwOyA1MSArPG86cD48L286cD48 L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQm9hcmRUaW9nYVBhc3MvT3BlbkJvYXJk UGtnLmRzYyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu YnNwOyZuYnNwOyB8Jm5ic3A7IDI0NSArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxh aW5UZXh0Ij4uLi4vQm9hcmRUaW9nYVBhc3MvT3BlbkJvYXJkUGtnLmZkZiZuYnNwOyZuYnNwOyZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7IDYw MCArKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0JvYXJkVGlv Z2FQYXNzL1BsYXRmb3JtUGtnQnVpbGRPcHRpb24uZHNjIHwmbmJzcDsmbmJzcDsgODQgKzxvOnA+ PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0JvYXJkVGlvZ2FQYXNzL1Bs YXRmb3JtUGtnQ29uZmlnLmRzYyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7 Jm5ic3A7IDU4ICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9C b2FyZFRpb2dhUGFzcy9QbGF0Zm9ybVBrZ1BjZC5kc2MmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyAzOTIgKys8bzpwPjwvbzpwPjwvcD4NCjxw IGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZFRpb2dhUGFzcy9TdHJ1Y3R1cmVDb25maWcu ZHNjJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwgNjIzNiArKysr KysrKysrKysrKysrKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4u L0JvYXJkVGlvZ2FQYXNzL19faW5pdF9fLnB5Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7IHwmbmJzcDsmbmJzcDsmbmJzcDsgMDxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1Bs YWluVGV4dCI+Li4uL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9ibGQuYmF0IHwm bmJzcDsgMTM5ICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9C b2FyZFRpb2dhUGFzcy9idWlsZF9ib2FyZC5weSZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNw OyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7IDE5NSAr PG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQm9hcmRUaW9nYVBh c3MvYnVpbGRfY29uZmlnLmNmZyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7Jm5ic3A7IDM0ICs8bzpwPjwvbzpwPjwvcD4N CjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2FyZFRpb2dhUGFzcy9sb2dvLnR4dCZuYnNw OyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7ICZu YnNwOzEwICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9Cb2Fy ZFRpb2dhUGFzcy9wb3N0YnVpbGQuYmF0Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJz cDsgOTYgKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0JvYXJk VGlvZ2FQYXNzL3ByZWJ1aWxkLmJhdCZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNw OyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7 IDIxMyArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vSXBtaS9M aWJyYXJ5L0lwbWlMaWJLY3MvSXBtaUxpYktjcy5pbmYmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNw OyZuYnNwOyAxMCArLTxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4u L0lwbWlQbGF0Zm9ybUhvb2tMaWIuaW5mJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJzcDsmbmJzcDsgNiArLTxvOnA+PC9vOnA+PC9w Pg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0luY2x1ZGUvR3VpZC9QY2hSY1ZhcmlhYmxl LmgmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyZuYnNwOyA2ICs8bzpwPjwvbzpw PjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9JbmNsdWRlL0d1aWQvU2V0dXBWYXJp YWJsZS5oJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJzcDsgMTUgKy08bzpwPjwvbzpw PjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQ a2cvT3BlbkJvYXJkUGtnLmRlYyB8Jm5ic3A7Jm5ic3A7Jm5ic3A7IDEgKzxvOnA+PC9vOnA+PC9w Pg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhlL0NvbXBvbmVu dE5hbWUuYyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8 Jm5ic3A7IDE3MCArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4v QnVzL1BjaS9QY2lCdXNEeGUvQ29tcG9uZW50TmFtZS5oJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsgMTQ2ICs8bzpwPjwvbzpwPjwvcD4NCjxw IGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUv UGNpQnVzLmMmbmJzcDsmbmJzcDsgfCZuYnNwOyA0NjAgKys8bzpwPjwvbzpwPjwvcD4NCjxwIGNs YXNzPSJNc29QbGFpblRleHQiPi4uLi9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNp QnVzLmgmbmJzcDsmbmJzcDsgfCZuYnNwOyAzOTYgKys8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNz PSJNc29QbGFpblRleHQiPi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lCdXNEeGUuaW5mJm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwm bmJzcDsgMTEyICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9C dXMvUGNpL1BjaUJ1c0R4ZS9QY2lCdXNEeGUudW5pJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJzcDsgMTYgKzxvOnA+ PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhl L1BjaUJ1c0R4ZUV4dHJhLnVuaSZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7 Jm5ic3A7IDE0ICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9C dXMvUGNpL1BjaUJ1c0R4ZS9QY2lDb21tYW5kLmMmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyAyNjcgKzxvOnA+ PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhl L1BjaUNvbW1hbmQuaCZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7IDIzMiArPG86cD48L286cD48L3A+DQo8cCBj bGFzcz0iTXNvUGxhaW5UZXh0Ij4uLi4vQnVzL1BjaS9QY2lCdXNEeGUvUGNpRGV2aWNlU3VwcG9y dC5jJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwgMTA1NiArKys8bzpwPjwvbzpwPjwv cD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lEZXZp Y2VTdXBwb3J0LmgmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyAyNjYgKzxv OnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0J1cy9QY2kvUGNpQnVz RHhlL1BjaURyaXZlck92ZXJyaWRlLmMmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyAx ODggKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4uL0J1cy9QY2kv UGNpQnVzRHhlL1BjaURyaXZlck92ZXJyaWRlLmgmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZu YnNwOyZuYnNwOyA4MyArPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij4u Li4vQnVzL1BjaS9QY2lCdXNEeGUvUGNpRW51bWVyYXRvci5jJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwgMjIxMCArKysrKys8bzpwPjwvbzpwPjwvcD4N CjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lFbnVtZXJh dG9yLmgmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZu YnNwOyA1MTUgKys8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPi4uLi9C dXMvUGNpL1BjaUJ1c0R4ZS9QY2lFbnVtZXJhdG9yU3VwcG9ydC5jJm5ic3A7IHwgMjg4NSArKysr KysrKyZuYnNwOyAuLi4vQnVzL1BjaS9QY2lCdXNEeGUvUGNpRW51bWVyYXRvclN1cHBvcnQuaCZu YnNwOyB8Jm5ic3A7IDQ4MCArKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4 dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUhvdFBsdWdTdXBwb3J0LmMmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsgfCZuYnNwOyA0ODQgKys8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29Q bGFpblRleHQiPi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lIb3RQbHVnU3VwcG9ydC5oJm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwmbmJzcDsgMjA1ICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNz PSJNc29QbGFpblRleHQiPi4uLi9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpSW8u YyZuYnNwOyZuYnNwOyZuYnNwOyB8IDIwODcgKysrKysrPG86cD48L286cD48L3A+DQo8cCBjbGFz cz0iTXNvUGxhaW5UZXh0Ij4uLi4vTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUlv LmgmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyA2NjAgKys8bzpwPjwvbzpwPjwvcD4NCjxwIGNs YXNzPSJNc29QbGFpblRleHQiPi4uLi9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNp TGliLmMmbmJzcDsmbmJzcDsgfCAxODA5ICsrKysrPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0i TXNvUGxhaW5UZXh0Ij4uLi4vTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUxpYi5o Jm5ic3A7Jm5ic3A7IHwmbmJzcDsgMTc5ICs8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29Q bGFpblRleHQiPi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lPcHRpb25Sb21TdXBwb3J0LmMmbmJz cDsmbmJzcDsgfCZuYnNwOyA3NzYgKys8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFp blRleHQiPi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lPcHRpb25Sb21TdXBwb3J0LmgmbmJzcDsm bmJzcDsgfCZuYnNwOyAxMzYgKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4 dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaVBvd2VyTWFuYWdlbWVudC5jJm5ic3A7Jm5ic3A7 Jm5ic3A7IHwmbmJzcDsmbmJzcDsgODIgKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1Bs YWluVGV4dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaVBvd2VyTWFuYWdlbWVudC5oJm5ic3A7 Jm5ic3A7Jm5ic3A7IHwmbmJzcDsmbmJzcDsgMjggKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9 Ik1zb1BsYWluVGV4dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaVJlc291cmNlU3VwcG9ydC5j Jm5ic3A7Jm5ic3A7Jm5ic3A7IHwgMjI5MiArKysrKys8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNz PSJNc29QbGFpblRleHQiPi4uLi9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lSZXNvdXJjZVN1cHBvcnQu aCZuYnNwOyZuYnNwOyZuYnNwOyB8Jm5ic3A7IDQ1NiArKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xh c3M9Ik1zb1BsYWluVGV4dCI+Li4uL0J1cy9QY2kvUGNpQnVzRHhlL1BjaVJvbVRhYmxlLmMmbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsg fCZuYnNwOyAxMzUgKzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Li4u L0J1cy9QY2kvUGNpQnVzRHhlL1BjaVJvbVRhYmxlLmgmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyA0OCArPG86 cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5QbGF0Zm9ybS9JbnRlbC9idWls ZC5jZmcmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyZuYnNwOyAyICs8bzpwPjwvbzpwPjwvcD4N CjxwIGNsYXNzPSJNc29QbGFpblRleHQiPlBsYXRmb3JtL0ludGVsL2J1aWxkX2Jpb3MucHkmbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgfCZuYnNwOyZuYnNwOyZu YnNwOyAzICstPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij44MCBmaWxl cyBjaGFuZ2VkLCAzMDI3OCBpbnNlcnRpb25zKCspLCAyNDAgZGVsZXRpb25zKC0pJm5ic3A7IGNy ZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRU aW9nYVBhc3MvQ29yZUR4ZUluY2x1ZGUuZHNjPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNv UGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJv YXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0NvcmVVZWZpQm9vdEluY2x1ZGUuZmRmPG86cD48L286cD48 L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0v SW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0dpdEVkazJNaW5UaW9nYVBh c3MuYmF0PG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9k ZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNz L0xpYnJhcnkvQmFzZVBsYXRmb3JtSG9va0xpYi9CYXNlUGxhdGZvcm1Ib29rTGliLmM8bzpwPjwv bzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0 Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3MvTGlicmFyeS9CYXNl UGxhdGZvcm1Ib29rTGliL0Jhc2VQbGF0Zm9ybUhvb2tMaWIuaW5mPG86cD48L286cD48L3A+DQo8 cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwv UHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRBY3BpTGliL0R4 ZUJvYXJkQWNwaVRhYmxlTGliLmM8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRl eHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cv Qm9hcmRUaW9nYVBhc3MvTGlicmFyeS9Cb2FyZEFjcGlMaWIvRHhlQm9hcmRBY3BpVGFibGVMaWIu aW5mPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAx MDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xp YnJhcnkvQm9hcmRBY3BpTGliL0R4ZVRpb2dhUGFzc0FjcGlUYWJsZUxpYi5jPG86cD48L286cD48 L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0v SW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRBY3Bp TGliL1NtbUJvYXJkQWNwaUVuYWJsZUxpYi5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNv UGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJv YXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRBY3BpTGliL1NtbUJvYXJkQWNwaUVu YWJsZUxpYi5pbmY8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0 ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9n YVBhc3MvTGlicmFyeS9Cb2FyZEFjcGlMaWIvU21tU2lsaWNvbkFjcGlFbmFibGVMaWIuYzxvOnA+ PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBs YXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0Jv YXJkQWNwaUxpYi9TbW1UaW9nYVBhc3NBY3BpRW5hYmxlTGliLmM8bzpwPjwvbzpwPjwvcD4NCjxw IGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9Q dXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3MvTGlicmFyeS9Cb2FyZEluaXRMaWIvQWxs TGFuZXNFcGFyYW0uYzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3Jl YXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRp b2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9HcGlvVGFibGUuYzxvOnA+PC9vOnA+PC9wPg0K PHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVs L1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9J aW9CaWZ1ci5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUg bW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQ YXNzL0xpYnJhcnkvQm9hcmRJbml0TGliL1BlaUJvYXJkSW5pdFBvc3RNZW1MaWIuYzxvOnA+PC9v OnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRm b3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJk SW5pdExpYi9QZWlCb2FyZEluaXRQb3N0TWVtTGliLmluZjxvOnA+PC9vOnA+PC9wPg0KPHAgY2xh c3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxl eU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9QZWlCb2Fy ZEluaXRQcmVNZW1MaWIuYzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+ Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2Fy ZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9QZWlCb2FyZEluaXRQcmVNZW1MaWIuaW5m PG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2 NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xpYnJh cnkvQm9hcmRJbml0TGliL1BlaVRpb2dhUGFzc0RldGVjdC5jPG86cD48L286cD48L3A+DQo8cCBj bGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVy bGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xpYnJhcnkvQm9hcmRJbml0TGliL1BlaVRp b2dhUGFzc0luaXRMaWIuaDxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+ Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2Fy ZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5pdExpYi9QZWlUaW9nYVBhc3NJbml0UG9zdE1lbUxp Yi5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAx MDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL0xp YnJhcnkvQm9hcmRJbml0TGliL1BlaVRpb2dhUGFzc0luaXRQcmVNZW1MaWIuYzxvOnA+PC9vOnA+ PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3Jt L0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L0JvYXJkSW5p dExpYi9Vc2JPQy5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVh dGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlv Z2FQYXNzL0xpYnJhcnkvUGVpUmVwb3J0RnZMaWIvUGVpUmVwb3J0RnZMaWIuYzxvOnA+PC9vOnA+ PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3Jt L0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9MaWJyYXJ5L1BlaVJlcG9y dEZ2TGliL1BlaVJlcG9ydEZ2TGliLmluZjxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1Bs YWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2Fy ZFBrZy9Cb2FyZFRpb2dhUGFzcy9PcGVuQm9hcmRQa2cuZHNjPG86cD48L286cD48L3A+DQo8cCBj bGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVy bGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL09wZW5Cb2FyZFBrZy5mZGY8bzpwPjwvbzpw PjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9y bS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3MvUGxhdGZvcm1Qa2dCdWls ZE9wdGlvbi5kc2M8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0 ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9n YVBhc3MvUGxhdGZvcm1Qa2dDb25maWcuZHNjPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNv UGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJv YXJkUGtnL0JvYXJkVGlvZ2FQYXNzL1BsYXRmb3JtUGtnUGNkLmRzYzxvOnA+PC9vOnA+PC9wPg0K PHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVs L1B1cmxleU9wZW5Cb2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9TdHJ1Y3R1cmVDb25maWcuZHNjPG86 cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQg UGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL19faW5pdF9f LnB5PG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAx MDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL2Js ZC5iYXQ8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2Rl IDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRUaW9nYVBhc3Mv YnVpbGRfYm9hcmQucHk8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNy ZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvQm9hcmRU aW9nYVBhc3MvYnVpbGRfY29uZmlnLmNmZzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1Bs YWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2Fy ZFBrZy9Cb2FyZFRpb2dhUGFzcy9sb2dvLnR4dDxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1z b1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5C b2FyZFBrZy9Cb2FyZFRpb2dhUGFzcy9wb3N0YnVpbGQuYmF0PG86cD48L286cD48L3A+DQo8cCBj bGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVy bGV5T3BlbkJvYXJkUGtnL0JvYXJkVGlvZ2FQYXNzL3ByZWJ1aWxkLmJhdDxvOnA+PC9vOnA+PC9w Pg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0lu dGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lC dXNEeGUvQ29tcG9uZW50TmFtZS5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5U ZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtn L092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9Db21wb25lbnROYW1lLmg8 bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0 NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtn L0J1cy9QY2kvUGNpQnVzRHhlL1BjaUJ1cy5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNv UGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJv YXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lCdXMuaDxv OnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0 IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cv QnVzL1BjaS9QY2lCdXNEeGUvUGNpQnVzRHhlLmluZjxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9 Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9w ZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpQnVz RHhlLnVuaTxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1v ZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVN b2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpQnVzRHhlRXh0cmEudW5pPG86cD48L286cD48 L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0v SW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1Bj aUJ1c0R4ZS9QY2lDb21tYW5kLmM8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRl eHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cv T3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaUNvbW1hbmQuaDxvOnA+ PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBs YXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVz L1BjaS9QY2lCdXNEeGUvUGNpRGV2aWNlU3VwcG9ydC5jPG86cD48L286cD48L3A+DQo8cCBjbGFz cz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5 T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lE ZXZpY2VTdXBwb3J0Lmg8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNy ZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJp ZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaURyaXZlck92ZXJyaWRlLmM8bzpw PjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQ bGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1 cy9QY2kvUGNpQnVzRHhlL1BjaURyaXZlck92ZXJyaWRlLmg8bzpwPjwvbzpwPjwvcD4NCjxwIGNs YXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJs ZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1Bj aUVudW1lcmF0b3IuYzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3Jl YXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlk ZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpRW51bWVyYXRvci5oPG86cD48L286 cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZv cm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNp L1BjaUJ1c0R4ZS9QY2lFbnVtZXJhdG9yU3VwcG9ydC5jPG86cD48L286cD48L3A+DQo8cCBjbGFz cz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5 T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lF bnVtZXJhdG9yU3VwcG9ydC5oPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0 Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092 ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lIb3RQbHVnU3VwcG9ydC5j PG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2 NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBr Zy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lIb3RQbHVnU3VwcG9ydC5oPG86cD48L286cD48L3A+DQo8 cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwv UHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4 ZS9QY2lJby5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUg bW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01k ZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lJby5oPG86cD48L286cD48L3A+DQo8cCBj bGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVy bGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9Q Y2lMaWIuYzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1v ZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVN b2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpTGliLmg8bzpwPjwvbzpwPjwvcD4NCjxwIGNs YXNzPSJNc29QbGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJs ZXlPcGVuQm9hcmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1Bj aU9wdGlvblJvbVN1cHBvcnQuYzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4 dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9P dmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpT3B0aW9uUm9tU3VwcG9y dC5oPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUgbW9kZSAx MDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01kZU1vZHVs ZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lQb3dlck1hbmFnZW1lbnQuYzxvOnA+PC9vOnA+PC9w Pg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0lu dGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lC dXNEeGUvUGNpUG93ZXJNYW5hZ2VtZW50Lmg8bzpwPjwvbzpwPjwvcD4NCjxwIGNsYXNzPSJNc29Q bGFpblRleHQiPmNyZWF0ZSBtb2RlIDEwMDY0NCBQbGF0Zm9ybS9JbnRlbC9QdXJsZXlPcGVuQm9h cmRQa2cvT3ZlcnJpZGUvTWRlTW9kdWxlUGtnL0J1cy9QY2kvUGNpQnVzRHhlL1BjaVJlc291cmNl U3VwcG9ydC5jPG86cD48L286cD48L3A+DQo8cCBjbGFzcz0iTXNvUGxhaW5UZXh0Ij5jcmVhdGUg bW9kZSAxMDA2NDQgUGxhdGZvcm0vSW50ZWwvUHVybGV5T3BlbkJvYXJkUGtnL092ZXJyaWRlL01k ZU1vZHVsZVBrZy9CdXMvUGNpL1BjaUJ1c0R4ZS9QY2lSZXNvdXJjZVN1cHBvcnQuaDxvOnA+PC9v OnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1BsYWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRm b3JtL0ludGVsL1B1cmxleU9wZW5Cb2FyZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1Bj aS9QY2lCdXNEeGUvUGNpUm9tVGFibGUuYzxvOnA+PC9vOnA+PC9wPg0KPHAgY2xhc3M9Ik1zb1Bs YWluVGV4dCI+Y3JlYXRlIG1vZGUgMTAwNjQ0IFBsYXRmb3JtL0ludGVsL1B1cmxleU9wZW5Cb2Fy ZFBrZy9PdmVycmlkZS9NZGVNb2R1bGVQa2cvQnVzL1BjaS9QY2lCdXNEeGUvUGNpUm9tVGFibGUu aDxvOnA+PC9vOnA+PC9wPg0KPGRpdj4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjwvbzpwPjwvc3Bh bj48L3A+DQo8L2Rpdj4NCjwvZGl2Pg0KPC9kaXY+DQo8L2Rpdj4NCi1UaGUgaW5mb3JtYXRpb24g Y29udGFpbmVkIGluIHRoaXMgbWVzc2FnZSBtYXkgYmUgY29uZmlkZW50aWFsIGFuZCBwcm9wcmll dGFyeSB0byBBbWVyaWNhbiBNZWdhdHJlbmRzIChBTUkpLiBUaGlzIGNvbW11bmljYXRpb24gaXMg aW50ZW5kZWQgdG8gYmUgcmVhZCBvbmx5IGJ5IHRoZSBpbmRpdmlkdWFsIG9yIGVudGl0eSB0byB3 aG9tIGl0IGlzIGFkZHJlc3NlZCBvciBieSB0aGVpciBkZXNpZ25lZS4gSWYgdGhlIHJlYWRlciBv ZiB0aGlzIG1lc3NhZ2UNCiBpcyBub3QgdGhlIGludGVuZGVkIHJlY2lwaWVudCwgeW91IGFyZSBv biBub3RpY2UgdGhhdCBhbnkgZGlzdHJpYnV0aW9uIG9mIHRoaXMgbWVzc2FnZSwgaW4gYW55IGZv cm0sIGlzIHN0cmljdGx5IHByb2hpYml0ZWQuIFBsZWFzZSBwcm9tcHRseSBub3RpZnkgdGhlIHNl bmRlciBieSByZXBseSBlLW1haWwgb3IgYnkgdGVsZXBob25lIGF0IDc3MC0yNDYtODYwMCwgYW5k IHRoZW4gZGVsZXRlIG9yIGRlc3Ryb3kgYWxsIGNvcGllcyBvZiB0aGUgdHJhbnNtaXNzaW9uLg0K PC9ib2R5Pg0KPC9odG1sPg0K --_000_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_-- --_004_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_ Content-Type: message/rfc822 Content-Disposition: attachment; creation-date="Thu, 17 Jun 2021 14:55:29 GMT"; modification-date="Thu, 17 Jun 2021 14:55:29 GMT" Received: from BYAPR10MB2456.namprd10.prod.outlook.com (2603:10b6:a02:b3::16) by PH0PR10MB4408.namprd10.prod.outlook.com with HTTPS; Thu, 17 Jun 2021 00:53:28 +0000 Received: from MW4PR04CA0020.namprd04.prod.outlook.com (2603:10b6:303:69::25) by BYAPR10MB2456.namprd10.prod.outlook.com (2603:10b6:a02:b3::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4242.18; Thu, 17 Jun 2021 00:53:22 +0000 Received: from MW2NAM12FT040.eop-nam12.prod.protection.outlook.com (2603:10b6:303:69:cafe::f9) by MW4PR04CA0020.outlook.office365.com (2603:10b6:303:69::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4219.21 via Frontend Transport; Thu, 17 Jun 2021 00:53:21 +0000 Received: from mga07.intel.com (134.134.136.100) by MW2NAM12FT040.mail.protection.outlook.com (10.13.180.228) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4219.9 via Frontend Transport; Thu, 17 Jun 2021 00:53:20 +0000 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 17:53:06 -0700 Received: from nldesimo-desk1.amr.corp.intel.com ([10.209.120.62]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 17:52:59 -0700 From: Nate DeSimone To: "devel@edk2.groups.io" CC: Manickavasakam Karpagavinayagam , Isaac Oram , Felix Polyudov , Harikrishna Doppalapudi , Manish Jha , Zachary Bobroff Subject: [EXTERNAL] [edk2-platforms] [PATCH V1 2/2] PurleyOpenBoardPkg : Override generic PciBus Driver with Platform specific instance of PciBus driver. Thread-Topic: [EXTERNAL] [edk2-platforms] [PATCH V1 2/2] PurleyOpenBoardPkg : Override generic PciBus Driver with Platform specific instance of PciBus driver. Thread-Index: AQHXYxMvG0uDVyKD2k2QL/s51PBNKw== Date: Thu, 17 Jun 2021 00:51:37 +0000 Message-ID: <20210617005137.2583-6-nathaniel.l.desimone@intel.com> References: <20210617005137.2583-1-nathaniel.l.desimone@intel.com> In-Reply-To: <20210617005137.2583-1-nathaniel.l.desimone@intel.com> Content-Language: en-US X-MS-Exchange-Organization-AuthSource: MW2NAM12FT040.eop-nam12.prod.protection.outlook.com X-MS-Has-Attach: X-MS-Exchange-Organization-Network-Message-Id: 2ad231d3-951a-4b3a-0726-08d9312a4daa X-MS-TNEF-Correlator: X-MS-Exchange-Organization-RecordReviewCfmType: 0 x-ms-exchange-organization-originalclientipaddress: 134.134.136.100 x-ms-exchange-organization-originalserveripaddress: 10.13.180.228 x-ironport-av: E=Sophos;i="5.83,278,1616482800"; d="scan'208";a="555016455" received-spf: Pass (protection.outlook.com: domain of intel.com designates 134.134.136.100 as permitted sender) receiver=protection.outlook.com; client-ip=134.134.136.100; helo=mga07.intel.com; x-ms-publictraffictype: Email x-ms-exchange-organization-submissionquotaskipped: False authentication-results: spf=pass (sender IP is 134.134.136.100) smtp.mailfrom=intel.com; ami.com; dkim=none (message not signed) header.d=none;ami.com; dmarc=pass action=none header.from=intel.com;compauth=pass reason=100 x-ms-office365-filtering-correlation-id: 2ad231d3-951a-4b3a-0726-08d9312a4daa x-ms-traffictypediagnostic: BYAPR10MB2456: x-forefront-antispam-report: CIP:134.134.136.100;CTRY:US;LANG:en;SCL:-1;SRV:;IPV:NLI;SFV:SKA;H:mga07.intel.com;PTR:ErrorRetry;CAT:NONE;SFS:;DIR:INB; x-ms-oob-tlc-oobclassifiers: OLM:655; x-microsoft-antispam: BCL:0; x-ms-exchange-crosstenant-network-message-id: 2ad231d3-951a-4b3a-0726-08d9312a4daa x-ms-exchange-crosstenant-originalarrivaltime: 17 Jun 2021 00:53:20.8593 (UTC) x-ms-exchange-crosstenant-fromentityheader: Internet x-ms-exchange-crosstenant-id: 27e97857-e15f-486c-b58e-86c2b3040f93 x-ms-exchange-transport-crosstenantheadersstamped: BYAPR10MB2456 x-ms-exchange-transport-endtoendlatency: 00:00:07.8450690 x-ms-exchange-processed-by-bccfoldering: 15.20.4242.019 x-ms-exchange-crosstenant-authas: Anonymous x-ms-exchange-crosstenant-authsource: MW2NAM12FT040.eop-nam12.prod.protection.outlook.com x-ms-exchange-atpmessageproperties: SA|SL x-eopattributedmessage: 0 x-eoptenantattributedmessage: 27e97857-e15f-486c-b58e-86c2b3040f93:0 X-Microsoft-Antispam-Mailbox-Delivery: ucf:0;jmr:0;auth:0;dest:I;ENG:(750129)(520011016)(944506458)(944626604); X-Microsoft-Antispam-Message-Info: =?iso-8859-1?Q?MmCUJAKqM30+wugua1OAwtW4LVOVofN5hPcpQyxFOxsSvprXjN5geD2PNv?= =?iso-8859-1?Q?mAzKVde8LG27gRR4zHYiAMMyKjWNO3aI+p5lEFbvPlb8N0BjIrG1CaD3Jv?= =?iso-8859-1?Q?ueDNTnxUTl16tZQXthPG6DRfwJ5YtqWxO9KV78Eljk1/57PviAVsyWI7vz?= =?iso-8859-1?Q?mkC5moL8cA4CzI4eSjQ8cv+l7w6AWY7JsCYMgpqerM8XKUyf1F9zEbD74P?= =?iso-8859-1?Q?09duktZsb/V2HSaYT7GCgjxoLlOBxT/4L4xE2sEQdLfo9Sdxb1sftMDiG+?= =?iso-8859-1?Q?z9qphLUuy8JQG2JCq5B359gw/BwjLrEqpDyoz4B4zyhE9Y9VLcpouGMxb3?= =?iso-8859-1?Q?FSx77oaTfmhJnoZckDGf0K38E1SQfWDdf3tJL14Fvv0Zp184x4R48wWfMh?= =?iso-8859-1?Q?PV5g7oH3iNBWLIb+e91OimU8BSxWDvQu4xlM3l6H2HyHUguqWTC+DrkrA7?= =?iso-8859-1?Q?xLeqW9CbeJCPbxBsw2SWEe+jp85n97RCyxFFF43mX0w+V+8HgpN6M/OpVT?= =?iso-8859-1?Q?TkOtjB+pU7qt/ZVbLQFcL/s5X4FVXtpCtIfwj+dd3x2Vu0OJ9o/FATmu95?= =?iso-8859-1?Q?4SFfmkeiNFhQBREDpN4OEjWLiPZ7eJM50p618OPANJFaTDDt92n8I0FeCG?= =?iso-8859-1?Q?ZNIj9fnmwROve0OLuW2Wr3lFgH0ZB1UWtvexoNeGAUZI5prshuX4vkTCSq?= =?iso-8859-1?Q?Hpy5iXnBPoroT21Qcy4qDKgcFdtJyplUCJQBQVSNdxCSj0gSm6oxW00fO0?= =?iso-8859-1?Q?R+Ax2MODnKKElcImiEUT/ftT+KkTPUiEtp/G3Jry9ZSDRQDV1v15cgMdxy?= =?iso-8859-1?Q?qdD/A7fKKrnWweuJVo7A1mzu4gY6UgkXdHnjppJsG56KxYvrOmCNenDAR+?= =?iso-8859-1?Q?EBQIy7ukXXDV0wTn71f9QCUSycWmebJz6uP2afX1PA87slgEyg8aBwOjsN?= =?iso-8859-1?Q?3yyb8zjZ7vVqMWyU1u8jLSiFPC9IQWwq1ZpYnuR5fz/zUSg9lwT+bkAP1F?= =?iso-8859-1?Q?vBS/rhgBFqzXUg+Y5NjGAFWXEoac1FInzzw4YwnEUwNkVSqP5B6PwiaUeX?= =?iso-8859-1?Q?jYzVMVDOQi4kaQFJucw5DagBaviNzpqQD+NftG37E231vPu1ks0nNGvcZ+?= =?iso-8859-1?Q?gQAnBqjRzwZpi+/qez/d4WaZq3c7k3bZFrNw1oD1rF3UIXgE7O00e8sXm/?= =?iso-8859-1?Q?uZVaZvq6kleuaLsGiZb82xM80+CNlfP0P1U/SQj8EjYRgeBna2r4ydrtqh?= =?iso-8859-1?Q?UrcOG5GzYNDJs5BaCiBuOiWJ1iIDwhWgoN3HuY1pK4wPjYWThL5qg9AQZS?= =?iso-8859-1?Q?FCVlDPrxACyrdKx22OoqUcnt54HIotisXFARoP0R8tcw6b2YLLA6ByErGr?= =?iso-8859-1?Q?JtEkDMMP9k9ZW1skVYukhg/FcYI8oB9U9gMz2SerTZm6AvhUlkDwjjsyZ0?= =?iso-8859-1?Q?FZKPnIMbSnq5zorXKBFZs2L6ZncNElv7w20LYmliCgfUClPYr66e+pdDqq?= =?iso-8859-1?Q?sH7VO/INC37dFEo/IqU4Cbs5EBUrpzB5/ZsK6ekD6gBQ1+TxDRPI9ejKkQ?= =?iso-8859-1?Q?/byL4sol96xyJjy/WZxQstGFovn79XfCidjMnc+R8csrWB1Spi9KnIEVjB?= =?iso-8859-1?Q?6cEZDdOWT4X42eXVcBGoMTdVLrDbXS6LFhB8Ie5IVqAZdbhodYfBWssjBH?= =?iso-8859-1?Q?m4RVx7rEn0g9sKVBUGyVAM1iQ0Py3AsrtTy6BeXXhXYz67fXu4LjAvqRLk?= =?iso-8859-1?Q?HgMactfcminidKjcHDcoxWAUEE4csxCN6b+HFLmAYUNsQoeeoLbZkyDtvE?= =?iso-8859-1?Q?a0mVm89+RpnFNl6UST0k4YYetWuULUk=3D?= Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 **CAUTION: The e-mail below is from an external source. Please exercise cau= tion before opening attachments, clicking links, or following guidance.** From: manickavasakam karpagavinayagam Overriden generic PciBus Driver with Platform specific instance of PciBus d= river To skip SPI controller initialization during PCI enumeration to avoid SET v= ariable 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 Cc: Isaac Oram Cc: Felix Polyudov Cc: Harikrishna Doppalapudi Cc: Manish Jha Cc: Zachary Bobroff Cc: Manickavasakam Karpagavinayagam --- .../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/PciBusDxe/ComponentName.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/ComponentName.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciBus.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciBus.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciBusDxe.inf create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciBusDxe.uni create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciBusDxeExtra.uni create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciCommand.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciCommand.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciDeviceSupport.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciDeviceSupport.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciDriverOverride.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciDriverOverride.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciEnumerator.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciEnumerator.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciEnumeratorSupport.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciEnumeratorSupport.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciHotPlugSupport.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciHotPlugSupport.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciIo.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciIo.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciLib.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciLib.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciOptionRomSupport.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciOptionRomSupport.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciPowerManagement.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciPowerManagement.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciResourceSupport.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciResourceSupport.h create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciRomTable.c create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg= /Bus/Pci/PciBusDxe/PciRomTable.h diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreDxeInclud= e.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 #MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf - MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +#TiogaPass Override START :Skip OPROM for specific Mellanox card & SPI Co= ntroller + #MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + $(PLATFORM_BOARD_PACKAGE)/Override/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus= Dxe.inf +#TiogaPass Override END MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf diff --git a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootI= nclude.fdf b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootI= nclude.fdf index 478a818546..141ce5dda3 100644 --- a/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.= fdf +++ b/Platform/Intel/PurleyOpenBoardPkg/BoardTiogaPass/CoreUefiBootInclude.= fdf @@ -42,7 +42,10 @@ INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetS= ystemRuntimeDxe.inf INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf #INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf -INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +#TiogaPass Override START :Skip OPROM for specific Mellanox card & SPI Con= troller + #INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + INF $(PLATFORM_BOARD_PACKAGE)/Override/MdeModulePkg/Bus/Pci/PciBusDxe/Pc= iBusDxe.inf +#TiogaPass Override END INF MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/ComponentName.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Md= eModulePkg/Bus/Pci/PciBusDxe/ComponentName.c new file mode 100644 index 0000000000..f3554507e2 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 gPciBusComponen= tName =3D { + PciBusComponentNameGetDriverName, + PciBusComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponen= tName2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControll= erName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPciBusDriverNameTa= ble[] =3D { + { "eng;en", (CHAR16 *) L"PCI Bus Driver" }, + { NULL , NULL } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= 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 speci= fied + 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_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + 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 specifie= d by + This and the language specified by Languag= e 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 supp= ort + 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 control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handl= e + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is th= e + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format= . + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + 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 va= lid + 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 curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +PciBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/ComponentName.h b/Platform/Intel/PurleyOpenBoardPkg/Override/Md= eModulePkg/Bus/Pci/PciBusDxe/ComponentName.h new file mode 100644 index 0000000000..fc3c672760 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= 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 speci= fied + 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_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + 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 specifie= d by + This and the language specified by Languag= e 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 supp= ort + 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 control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handl= e + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is th= e + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format= . + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + 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 va= lid + 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 curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +PciBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +#endif diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/PciBus.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciBus.c new file mode 100644 index 0000000000..682b2dac38 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 one = 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 t= o manage all + PCI Root Bridges. So it means platform needs install PCI Root Bridge IO = 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 *gIncompatiblePciDeviceSuppo= rt =3D NULL; +UINTN gPciHostBridgeNumber =3D 0; +BOOLEAN gFullEnumeration =3D TRU= E; +UINT64 gAllOne =3D 0xF= FFFFFFFFFFFFFFFULL; +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 mPciHotPlug= Request =3D { + PciHotPlugRequestNotify +}; + +/** + The Entry Point for PCI Bus module. The user code starts with this funct= ion. + + Installs driver module protocols and. Creates virtual device handles for= ConIn, + ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex = protocol, + Simple Pointer protocol, Absolute Pointer protocol on those virtual hand= lers. + Installs Graphics Output protocol and/or UGA Draw protocol if needed. + + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e. + @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 entry = 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 protocol= . + // + Handle =3D NULL; + Status =3D gBS->InstallProtocolInterface ( + &Handle, + &gEfiPciHotPlugRequestProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPciHotPlugRequest + ); + } + + return Status; +} + +/** + Test to see if this driver supports ControllerHandle. Any ControllerHand= le + than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supporte= d. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific ch= ild + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this devic= e. + @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 tes= t + // + 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() funct= ion + // + 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 c= hild + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHandle. + @retval EFI_ALREADY_STARTED This driver is already running on Controlle= rHandle. + @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 phas= e + // + gPciPlatformProtocol =3D NULL; + gBS->LocateProtocol ( + &gEfiPciPlatformProtocolGuid, + NULL, + (VOID **) &gPciPlatformProtocol + ); + + // + // If PCI Platform protocol doesn't exist, try to Pci Override Protocol. + // + 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 information= 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->ParentHandle)= ; + } + } else { + // + // If PCI bus has already done the full enumeration, never do it again + // + 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 handles + 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 num= ber 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/Pc= i/PciBusDxe/PciBus.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciBus.h new file mode 100644 index 0000000000..967933e278 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 requir= ed 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 b= een 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 tha= n 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 *gIncompatiblePciDevic= eSupport; +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[P= CI_MAX_HOST_BRIDGE_NUM]; +extern UINT64 gAllOne; +extern UINT64 gAllZero; +extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; +extern EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; +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_DIS= PLAY_OTHER) + +/** + Test to see if this driver supports ControllerHandle. Any ControllerHand= le + than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supporte= d. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific ch= ild + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this devic= e. + @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 c= hild + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHandle. + @retval EFI_ALREADY_STARTED This driver is already running on Controlle= rHandle. + @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 handles + 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 num= ber 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/Pc= i/PciBusDxe/PciBusDxe.inf b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeM= odulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf new file mode 100644 index 0000000000..9d999f973b --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/PciBusDxe.inf @@ -0,0 +1,112 @@ +## @file +# The PCI bus driver will probe all PCI devices and allocate MMIO and IO = 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-0090273FC14D + 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 the = 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 ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPciBridgeIoAlignmentProbe ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdUnalignedPciIoEnable ## CON= SUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeResourceForOptionRom ## CON= SUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize ## SOMETIM= ES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport ## CONSUME= S + gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport ## CONSUME= S + gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport ## CONSUME= S + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration ## SOMETIM= ES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarSupport ## CONSUME= S + +[UserExtensions.TianoCore."ExtraFiles"] + PciBusDxeExtra.uni diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/PciBusDxe.uni b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeM= odulePkg/Bus/Pci/PciBusDxe/PciBusDxe.uni new file mode 100644 index 0000000000..81bfc2c9ef --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/PciBusDxe.uni @@ -0,0 +1,16 @@ +// /** @file +// The PCI bus driver will probe all PCI devices and allocate MMIO and IO = 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 de= vices and allocate MMIO and IO space for these devices" + +#string STR_MODULE_DESCRIPTION #language en-US "Please use PCD fe= ature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting." + diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/PciBusDxeExtra.uni b/Platform/Intel/PurleyOpenBoardPkg/Override= /MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxeExtra.uni new file mode 100644 index 0000000000..f6a7cdae00 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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/Pc= i/PciBusDxe/PciCommand.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeMo= dulePkg/Bus/Pci/PciBusDxe/PciCommand.c new file mode 100644 index 0000000000..3111448643 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/PciCommand.c @@ -0,0 +1,267 @@ +/** @file + PCI command register operations supporting 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" + +/** + 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 for= the PCI controller. + @param Operation Type of Operation. + @param PtrCommand Return buffer holding old PCI command, if operatio= n 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 block. + @retval EFI_UNSUPPORTED Pci device does not support capability. + @retval EFI_NOT_FOUND Pci device support but can not find register bl= ock. + +**/ +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 0x00)= ) { + 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 itse= lf, + // 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 block. + @retval EFI_UNSUPPORTED Pci device does not support capability. + @retval EFI_NOT_FOUND Pci device support but can not find register bl= ock. + +**/ +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/Pc= i/PciBusDxe/PciCommand.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeMo= dulePkg/Bus/Pci/PciBusDxe/PciCommand.h new file mode 100644 index 0000000000..5eabd56bf2 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/PciCommand.h @@ -0,0 +1,232 @@ +/** @file + PCI command register operations 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_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 for= the PCI controller. + @param Operation Type of Operation. + @param PtrCommand Return buffer holding old PCI command, if operatio= n 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 block. + @retval EFI_UNSUPPORTED Pci device does not support capability. + @retval EFI_NOT_FOUND Pci device support but can not find register bl= ock. + +**/ +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 block. + @retval EFI_UNSUPPORTED Pci device does not support capability. + @retval EFI_NOT_FOUND Pci device support but can not find register bl= ock. + +**/ +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 re= gister. + + @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, NU= LL) + +/** + Macro that enables command register. + + @param a[in] Pointer to instance of PCI_IO_DEVICE. + @param b[in] The enabled value written into command register. + + @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 register= . + + @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 register. + + @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 register= . + + @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/Pc= i/PciBusDxe/PciDeviceSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Override= /MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c new file mode 100644 index 0000000000..7effbd5053 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 exist= ), attaches + appropriate protocols onto the handle, does necessary initialization, an= d 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 the = PCI IO device. + + @retval EFI_SUCCESS The PCI device is successfully registered. + @retval other An error occurred when registering the PCI device. + +**/ +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 enum= eration + // + 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 enum= eration + // + 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, PciIoDevic= e->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 b= ridge 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 devic= e. + +**/ +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->Child= List) { + 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 B= ridge. + + @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->ChildList)= { + + 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 && Pci= IoDevice->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 && Pci= IoDevice->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 HostBridgeHandle)= { + + 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/Pc= i/PciBusDxe/PciDeviceSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Override= /MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h new file mode 100644 index 0000000000..acc0edc0bb --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 exist= ), attaches + appropriate protocols onto the handle, does necessary initialization, an= d 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 the = PCI IO device. + + @retval EFI_SUCCESS The PCI device is successfully registered. + @retval other An error occurred when registering the PCI device. + +**/ +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 b= ridge 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 devic= e. + +**/ +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 B= ridge. + + @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/Pc= i/PciBusDxe/PciDriverOverride.c b/Platform/Intel/PurleyOpenBoardPkg/Overrid= e/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c new file mode 100644 index 0000000000..0c3f684c8c --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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], &gEfiLoadedImageDevice= PathProtocolGuid, (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 co= ntroller. + + @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_O= VERRIDE_PROTOCOL instance. + @param DriverImageHandle On input, a pointer to the previous driver= image handle returned + by GetDriver(). On output, a pointer to th= e next driver + image handle. Passing in a NULL, will retu= rn the first driver + image handle. + + @retval EFI_SUCCESS A bus specific override driver is returned= in DriverImageHandle. + @retval EFI_NOT_FOUND The end of the list of override drivers wa= s reached. + A bus specific override driver is not retu= rned 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 *DriverImageHa= ndle + ) +{ + 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->Drive= rImagePath); + } + + if (Override->DriverImageHandle =3D=3D NULL) { + // + // The Option ROM identified by Override->DriverImagePath is not l= oaded. + // + 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 gEfiLoade= dImageProtocolGuid. + +**/ +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 both= . + // + ASSERT ((DriverImageHandle =3D=3D NULL) || (DriverImagePath =3D=3D NULL)= ); + + 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/Pc= i/PciBusDxe/PciDriverOverride.h b/Platform/Intel/PurleyOpenBoardPkg/Overrid= e/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h new file mode 100644 index 0000000000..ab058fa762 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 gEfiLoade= dImageProtocolGuid. + +**/ +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 co= ntroller. + + @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_O= VERRIDE_PROTOCOL instance. + @param DriverImageHandle On input, a pointer to the previous driver= image handle returned + by GetDriver(). On output, a pointer to th= e next driver + image handle. Passing in a NULL, will retu= rn the first driver + image handle. + + @retval EFI_SUCCESS A bus specific override driver is returned= in DriverImageHandle. + @retval EFI_NOT_FOUND The end of the list of override drivers wa= s reached. + A bus specific override driver is not retu= rned 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 *DriverImageHa= ndle + ); + +#endif diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/PciEnumerator.c b/Platform/Intel/PurleyOpenBoardPkg/Override/Md= eModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c new file mode 100644 index 0000000000..4e1c328b7e --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/PciEnumerator.c @@ -0,0 +1,2210 @@ +/** @file + PCI eunmeration implementation on entire PCI bus system for PCI Bus modu= le. + +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 bus = 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_EN= D_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, PaddedBusR= ange, &SubBusNumber); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find the bus range which contains the higest bus number, then returns= the number of buses + // that should be decoded. + // + while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBus= Number) { + Configuration++; + } + AddrLen =3D Configuration->AddrLen; + Configuration->AddrLen =3D SubBusNumber - Configuration->AddrRangeMin + = 1; + + // + // Save the Desc field of the next descriptor. Mark the next descriptor = 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, SubBusN= umber); + if (EFI_ERROR (Status)) { + return Status; + } + SecondBus =3D *SubBusNumber; + + Register =3D (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber= ); + + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18)= ; + + 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 interfaci= ng + 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 al= location 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 p= rotocol + // 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_ALL= OCATION_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 attri= bute. + +**/ +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 No= de. + @param PMem32Pool Pointer to instance of 32-bit Prefetchable memor= y resource node. + @param Mem64Pool Pointer to instance of 64-bit memory resource no= de. + @param PMem64Pool Pointer to instance of 64-bit Prefetchable memor= y 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 no= de. + @param Mem64ResStatus Status of 64-bit memory resource node. + @param PMem64ResStatus Status of 64-bit Prefetchable memory resource no= de. + + @retval EFI_SUCCESS Successfully adjusted resource on host bridge. + @retval EFI_ABORTED Host bridge hasn't this resource type or no reso= urce 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, P= ciResNode->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->PciDe= v->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 rejec= ted + // + 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 No= de + @param PMem32Node Pointer to instance of 32-bit Pmemory resource n= ode + @param Mem64Node Pointer to instance of 64-bit memory resource no= de + @param PMem64Node Pointer to instance of 64-bit Pmemory resource n= ode + @param Config Output buffer holding new constructed APCI resou= rce 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_DES= CRIPTOR) * 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_DESCRIPTO= R) - 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_DESCRIPTO= R) - 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_DESCRIPTO= R) - 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_DESCRIPTO= R) - 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_DESCRIPTO= R) - 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_DESCRIPTO= R)); + 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 r= oot 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 resour= ce. + @param Mem64Base Output for base address of 64-bit memory type resource= . + @param PMem64Base Output for base address of 64-bit Pmemory type resourc= e. + + @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 pe= rform specific actions, + including any chipset-specific initialization, so that the chipset is r= eady to enter the next phase. + Eight notification points are defined at this time. See belows: + EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apert= ures and internal data + structures. The PCI enumerator s= hould issue this notification + before starting a fresh enumerat= ion process. Enumeration cannot + be restarted after sending any o= ther notification such as + EfiPciHostBridgeBeginBusAllocati= on. + EfiPciHostBridgeBeginBusAllocation The bus allocation phase is abou= t to begin. No specific action is + required here. This notification= can be used to perform any + chipset-specific programming. + EfiPciHostBridgeEndBusAllocation The bus allocation and bus progr= amming phase is complete. No + specific action is required here= . This notification can be used to + perform any chipset-specific pro= gramming. + EfiPciHostBridgeBeginResourceAllocation + The resource allocation phase is= about to begin. No specific + action is required here. This no= tification can be used to perform + any chipset-specific programming= . + EfiPciHostBridgeAllocateResources Allocates resources per previous= ly submitted requests for all the PCI + root bridges. These resource set= tings are returned on the next call to + GetProposedResources(). Before c= alling NotifyPhase() with a Phase of + EfiPciHostBridgeAllocateResource= , the PCI bus enumerator is responsible + for gathering I/O and memory req= uests for + all the PCI root bridges and sub= mitting these requests using + SubmitResources(). This function= pads the resource amount + to suit the root bridge hardware= , takes care of dependencies between + the PCI root bridges, and calls = the Global Coherency Domain (GCD) + with the allocation request. In = the case of padding, the allocated range + could be bigger than what was re= quested. + EfiPciHostBridgeSetResources Programs the host bridge hardwar= e to decode previously allocated + resources (proposed resources) f= or all the PCI root bridges. After the + hardware is programmed, reassign= ing resources will not be supported. + The bus settings are not affecte= d. + EfiPciHostBridgeFreeResources Deallocates resources that were = previously allocated for all the PCI + root bridges and resets the I/O = and memory apertures to their initial + state. The bus settings are not = affected. If the request to allocate + resources fails, the PCI enumera= tor can use this notification to + deallocate previous resources, a= djust the requests, and retry + allocation. + EfiPciHostBridgeEndResourceAllocation The resource allocation phase is= completed. No specific action is + required here. This notification= can be used to perform any chipsetspecific + programming. + + @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRI= DGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in] Phase The phase during enumeration + + @retval EFI_NOT_READY This phase cannot be entered at this tim= e. For example, this error + is valid for a Phase of EfiPciHostBridge= AllocateResources if + SubmitResources() has not been called fo= r one or more + PCI root bridges before this call + @retval EFI_DEVICE_ERROR Programming failed due to a hardware err= or. This error is valid + for a Phase of EfiPciHostBridgeSetResour= ces. + @retval EFI_INVALID_PARAMETER Invalid phase parameter + @retval EFI_OUT_OF_RESOURCES The request could not be completed due t= o a lack of resources. + This error is valid for a Phase of EfiPc= iHostBridgeAllocateResources if the + previously submitted resource requests c= annot be fulfilled or + were only partially fulfilled. + @retval EFI_SUCCESS The notification was accepted without an= y 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 (devi= ce/function) at various + stages of the PCI enumeration process that allow the host bridge driver = to preinitialize individual + PCI controllers before enumeration. + + This function is called during the PCI enumeration process. No specific = action is expected from this + member function. It allows the host bridge driver to preinitialize indiv= idual PCI controllers before + enumeration. + + @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALL= OCATION_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 returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root br= idge handle. + @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defi= ned in + EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_= PHASE. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware er= ror. The PCI enumerator should + not enumerate this device, including it= s 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 request= ed when a hot-plug event has + happened on the hot-plug controller. Currently, the operations include a= dd operation and remove operation.. + + @param This A pointer to the hot plug request protocol. + @param Operation The operation the PCI bus driver is requeste= d to make. + @param Controller The handle of the hot-plug controller. + @param RemainingDevicePath The remaining device path for the PCI-like h= ot-plug device. + @param NumberOfChildren The number of child handles. + For a add operation, it is an output paramet= er. + For a remove operation, it's an input parame= ter. + @param ChildHandleBuffer The buffer which contains the child handles. + + @retval EFI_INVALID_PARAMETER Operation is not a legal value. + Controller is NULL or not a valid handle. + NumberOfChildren is NULL. + ChildHandleBuffer is NULL while Operation= is add. + @retval EFI_OUT_OF_RESOURCES There are no enough resources to start th= e devices. + @retval EFI_NOT_FOUND Can not find bridge according to controll= er handle. + @retval EFI_SUCCESS The handles for the specified device have= been created or destroyed + as requested, and for an add operation, t= he 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 EfiPciHo= tplugRequestRemove)) { + return EFI_INVALID_PARAMETER; + } + + if (Operation =3D=3D EfiPciHotPlugRequestAdd){ + if (ChildHandleBuffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + } else if ((Operation =3D=3D EfiPciHotplugRequestRemove) && (*NumberOfCh= ildren !=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/Pc= i/PciBusDxe/PciEnumerator.h b/Platform/Intel/PurleyOpenBoardPkg/Override/Md= eModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h new file mode 100644 index 0000000000..2a34c9043c --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 bus = 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 interfaci= ng + 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_ALL= OCATION_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 attri= bute. + +**/ +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 No= de. + @param PMem32Pool Pointer to instance of 32-bit Prefetchable memor= y resource node. + @param Mem64Pool Pointer to instance of 64-bit memory resource no= de. + @param PMem64Pool Pointer to instance of 64-bit Prefetchable memor= y 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 no= de. + @param Mem64ResStatus Status of 64-bit memory resource node. + @param PMem64ResStatus Status of 64-bit Prefetchable memory resource no= de. + + @retval EFI_SUCCESS Successfully adjusted resource on host bridge. + @retval EFI_ABORTED Host bridge hasn't this resource type or no reso= urce 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 No= de + @param PMem32Node Pointer to instance of 32-bit Pmemory resource n= ode + @param Mem64Node Pointer to instance of 64-bit memory resource no= de + @param PMem64Node Pointer to instance of 64-bit Pmemory resource n= ode + @param Config Output buffer holding new constructed APCI resou= rce 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 resour= ce. + @param Mem64Base Output for base address of 64-bit memory type resource= . + @param PMem64Base Output for base address of 64-bit Pmemory type resourc= e. + + @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_A= LLOCATION_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 pe= rform specific actions, + including any chipset-specific initialization, so that the chipset is r= eady to enter the next phase. + Eight notification points are defined at this time. See belows: + EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apert= ures and internal data + structures. The PCI enumerator s= hould issue this notification + before starting a fresh enumerat= ion process. Enumeration cannot + be restarted after sending any o= ther notification such as + EfiPciHostBridgeBeginBusAllocati= on. + EfiPciHostBridgeBeginBusAllocation The bus allocation phase is abou= t to begin. No specific action is + required here. This notification= can be used to perform any + chipset-specific programming. + EfiPciHostBridgeEndBusAllocation The bus allocation and bus progr= amming phase is complete. No + specific action is required here= . This notification can be used to + perform any chipset-specific pro= gramming. + EfiPciHostBridgeBeginResourceAllocation + The resource allocation phase is= about to begin. No specific + action is required here. This no= tification can be used to perform + any chipset-specific programming= . + EfiPciHostBridgeAllocateResources Allocates resources per previous= ly submitted requests for all the PCI + root bridges. These resource set= tings are returned on the next call to + GetProposedResources(). Before c= alling NotifyPhase() with a Phase of + EfiPciHostBridgeAllocateResource= , the PCI bus enumerator is responsible + for gathering I/O and memory req= uests for + all the PCI root bridges and sub= mitting these requests using + SubmitResources(). This function= pads the resource amount + to suit the root bridge hardware= , takes care of dependencies between + the PCI root bridges, and calls = the Global Coherency Domain (GCD) + with the allocation request. In = the case of padding, the allocated range + could be bigger than what was re= quested. + EfiPciHostBridgeSetResources Programs the host bridge hardwar= e to decode previously allocated + resources (proposed resources) f= or all the PCI root bridges. After the + hardware is programmed, reassign= ing resources will not be supported. + The bus settings are not affecte= d. + EfiPciHostBridgeFreeResources Deallocates resources that were = previously allocated for all the PCI + root bridges and resets the I/O = and memory apertures to their initial + state. The bus settings are not = affected. If the request to allocate + resources fails, the PCI enumera= tor can use this notification to + deallocate previous resources, a= djust the requests, and retry + allocation. + EfiPciHostBridgeEndResourceAllocation The resource allocation phase is= completed. No specific action is + required here. This notification= can be used to perform any chipsetspecific + programming. + + @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRI= DGE_RESOURCE_ALLOCATION_PROTOCOL + @param[in] Phase The phase during enumeration + + @retval EFI_NOT_READY This phase cannot be entered at this tim= e. For example, this error + is valid for a Phase of EfiPciHostBridge= AllocateResources if + SubmitResources() has not been called fo= r one or more + PCI root bridges before this call + @retval EFI_DEVICE_ERROR Programming failed due to a hardware err= or. This error is valid + for a Phase of EfiPciHostBridgeSetResour= ces. + @retval EFI_INVALID_PARAMETER Invalid phase parameter + @retval EFI_OUT_OF_RESOURCES The request could not be completed due t= o a lack of resources. + This error is valid for a Phase of EfiPc= iHostBridgeAllocateResources if the + previously submitted resource requests c= annot be fulfilled or + were only partially fulfilled. + @retval EFI_SUCCESS The notification was accepted without an= y 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 (devi= ce/function) at various + stages of the PCI enumeration process that allow the host bridge driver = to preinitialize individual + PCI controllers before enumeration. + + This function is called during the PCI enumeration process. No specific = action is expected from this + member function. It allows the host bridge driver to preinitialize indiv= idual PCI controllers before + enumeration. + + @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALL= OCATION_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 returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root br= idge handle. + @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defi= ned in + EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_= PHASE. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware er= ror. The PCI enumerator should + not enumerate this device, including it= s 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 request= ed when a hot-plug event has + happened on the hot-plug controller. Currently, the operations include a= dd operation and remove operation.. + + @param This A pointer to the hot plug request protocol. + @param Operation The operation the PCI bus driver is requeste= d to make. + @param Controller The handle of the hot-plug controller. + @param RemainingDevicePath The remaining device path for the PCI-like h= ot-plug device. + @param NumberOfChildren The number of child handles. + For a add operation, it is an output paramet= er. + For a remove operation, it's an input parame= ter. + @param ChildHandleBuffer The buffer which contains the child handles. + + @retval EFI_INVALID_PARAMETER Operation is not a legal value. + Controller is NULL or not a valid handle. + NumberOfChildren is NULL. + ChildHandleBuffer is NULL while Operation= is add. + @retval EFI_OUT_OF_RESOURCES There are no enough resources to start th= e devices. + @retval EFI_NOT_FOUND Can not find bridge according to controll= er handle. + @retval EFI_SUCCESS The handles for the specified device have= been created or destroyed + as requested, and for an add operation, t= he 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/Pc= i/PciBusDxe/PciEnumeratorSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Over= ride/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c new file mode 100644 index 0000000000..99b04a462b --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 *mDeviceSec= urityProtocol; + +#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_P= ROTOCOL. + @param Pci Output buffer for PCI device configuration spac= e. + @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 otherwi= se SPI access runing DXE/DXE SMM +// will causes failures writting to SPI. This is a WA for LBG since curren= tly 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 SKI= P\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 to = 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 inform= ation. + +**/ +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, Func= , 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 bridge= s + // + // + if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRI= DGE (&Pci))) { + + // + // If it is PPB, we need to get the secondary bus to continue th= e enumeration + // + PciIo =3D &(PciIoDevice->PciIo); + + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRID= GE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Ensure secondary bus number is greater than the primary bus n= umber to avoid + // any potential dead loop when PcdPciDisableBusEnumeration is s= et 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 some = 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 reso= urces. +**/ +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 PciBarType= Io32) { + ResourceType =3D PciBarTypeIo; + } + + for (Descriptor =3D PciIoDevice->ResourcePaddingDescriptors; Descriptor-= >Desc !=3D ACPI_END_TAG_DESCRIPTOR; Descriptor++) { + + Type =3D PciBarTypeUnknown; + if (Descriptor->Desc =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR && Descripto= r->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_IO) { + Type =3D PciBarTypeIo; + } else if (Descriptor->Desc =3D=3D ACPI_ADDRESS_SPACE_DESCRIPTOR && De= scriptor->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_MEM) { + + if (Descriptor->AddrSpaceGranularity =3D=3D 32) { + // + // prefetchable + // + if (Descriptor->SpecificFlag =3D=3D EFI_ACPI_MEMORY_RESOURCE_SPECI= FIC_FLAG_CACHEABLE_PREFETCHABLE) { + 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_SPECI= FIC_FLAG_CACHEABLE_PREFETCHABLE) { + Type =3D PciBarTypePMem64; + } + + // + // Non-prefetchable + // + if (Descriptor->SpecificFlag =3D=3D 0) { + Type =3D PciBarTypeMem64; + } + } + } + + if ((Type !=3D PciBarTypeUnknown) && ((ResourceType =3D=3D PciBarTypeU= nknown) || (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;\tO= ffset =3D 0x%02x\n", + Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTy= peMaxType)], + PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Len= gth, 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;\tO= ffset =3D 0x%02x\n", + Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBar= TypeMaxType)], + 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_CAPABILI= TY_ID_SRIOV_BAR0, BarIndex =3D 0; + Offset <=3D PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABIL= ITY_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_CONTR= OL_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 4K. + // + + 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 supported= by this bridge. + // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its co= ntent 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 Prefetchab= le 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_CO= NTROL_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, &Pci= Node.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, &Origina= lValue); + + // + // Raise TPL to high level to disable timer interrupt while the BAR is p= robed + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOn= e); + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value); + + // + // Write back the original value + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Origin= alValue); + + // + // 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, &Origina= lValue); + + // + // Raise TPL to high level to disable timer interrupt while the BAR is p= robed + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOn= e); + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value); + + // + // Write back the original value + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Origin= alValue); + + // + // 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 p= robed + // + 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_ATTRI= BUTES. + +**/ +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_ATTRIBUT= E_ISA_IO : \ + (UINT64) EFI_PCI_IO_ATTRIBUTE_= ISA_IO_16); + } + + if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevi= ce->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_ATTRIBUT= E_VGA_IO : \ + (UINT64) EFI_PCI_IO_ATTRIBUTE_= VGA_IO_16); + } + } + + PciIoDevice->Supports =3D Attributes; + PciIoDevice->Supports &=3D ( (PciIoDevice->Parent->Supports) | \ + EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIB= UTE_MEMORY | \ + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER ); + + } else { + // + // When this attribute is clear, the RomImage and RomSize fields in th= e PCI IO were + // initialized based on the PCI option ROM found through the ROM BAR o= f the PCI controller. + // When this attribute is set, the PCI option ROM described by the Rom= Image 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 attribut= e. + @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back = 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 PCI = 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 childre= n + // + CurrentLink =3D PciIoDevice->ChildList.ForwardLink; + while (CurrentLink !=3D NULL && CurrentLink !=3D &PciIoDevice->ChildList= ) { + + 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_DEVI= CE | + 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 or = P2C + // Since some devices only support part of them, it is better to set t= he + // 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, &Old= Command, &OldBridgeControl); + + // + // Set the supported attributes for specified PCI device + // + PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SU= PPORTS); + + // + // 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_PRO= TOCOL + // For PCI Express devices, Memory Write and Invalidate is hardwired t= o 0b so only enable it for PCI devices. + if (!PciIoDevice->IsPciExp) { + PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRI= TE_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 childre= n + // + CurrentLink =3D PciIoDevice->ChildList.ForwardLink; + while (CurrentLink !=3D NULL && CurrentLink !=3D &PciIoDevice->ChildList= ) { + + 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_C= ONTROL_FAST_BACK_TO_BACK); + } else { + PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CO= NTROL_FAST_BACK_TO_BACK); + } + } + + CurrentLink =3D PciIoDevice->ChildList.ForwardLink; + while (CurrentLink !=3D NULL && CurrentLink !=3D &PciIoDevice->ChildLi= st) { + Temp =3D PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (FastB2BSupport) { + PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BA= CK); + } else { + PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_B= ACK); + } + + CurrentLink =3D CurrentLink->ForwardLink; + } + } + // + // End for IsListEmpty + // + return EFI_SUCCESS; +} + +/** + This routine is used to update the bar information for those incompatibl= e PCI device. + + @param PciIoDevice Input Pci device instance. Output Pci device ins= tance 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 pro= tocol or not + // If it is , then get its special requirement in the ACPI table + // + Status =3D gIncompatiblePciDeviceSupport->CheckDevice ( + gIncompatiblePciDeviceSupp= ort, + PciIoDevice->Pci.Hdr.Vendo= rId, + PciIoDevice->Pci.Hdr.Devic= eId, + PciIoDevice->Pci.Hdr.Revis= ionID, + PciIoDevice->Pci.Device.Su= bsystemVendorID, + PciIoDevice->Pci.Device.Su= bsystemID, + &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 M= AX_UINT8 (wide match). + // Skip updating when current BarIndex doesn't equal to AddrTransl= ationOffset. + // 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 PciBarTypeMem64= ) { + 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 PciBarTypePMem6= 4) { + 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->Addr= RangeMax); + + // + // 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 instance. + + @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->SystemP= ageSize - 1) { + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice->SystemP= ageSize - 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, n= ext 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->SystemP= ageSize - 1) { + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice->SystemP= ageSize - 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 ((UINT64)= OriginalValue, 32); + + PciIoDevice->VfPciBar[BarIndex].Length =3D PciIoDevice->VfPciBar[= BarIndex].Length | LShiftU64 ((UINT64) Value, 32); + PciIoDevice->VfPciBar[BarIndex].Length =3D (~(PciIoDevice->VfPciB= ar[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->SystemP= ageSize - 1) { + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice->SystemP= ageSize - 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->SystemP= ageSize - 1) { + PciIoDevice->VfPciBar[BarIndex].Alignment =3D PciIoDevice->SystemP= ageSize - 1; + } + + break; + } + } + + // + // Check the length again so as to keep compatible with some special bar= s + // + 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 all = 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[BarI= ndex].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[BarI= ndex].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 fo= r Directed I/O + // + PciIoDevice->PciBar[BarIndex].Alignment =3D (SIZE_4KB - 1); + } else { + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice->PciBar[Ba= rIndex].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, n= ext 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[BarI= ndex].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 the= low 32 bit BAR again + // + if (PciIoDevice->PciBar[BarIndex].Length =3D=3D 0) { + // + // some device implement MMIO bar with 0 length, need to treat i= t 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 MEM64 = 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) O= riginalValue, 32); + + PciIoDevice->PciBar[BarIndex].Length =3D PciIoDevice->PciBar[BarI= ndex].Length | LShiftU64 ((UINT64) Value, 32); + PciIoDevice->PciBar[BarIndex].Length =3D (~(PciIoDevice->PciBar[B= arIndex].Length)) + 1; + if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) { + // + // Force minimum 4KByte alignment for Virtualization technology fo= r Directed I/O + // + PciIoDevice->PciBar[BarIndex].Alignment =3D (SIZE_4KB - 1); + } else { + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice->PciBar[Ba= rIndex].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 fo= r Directed I/O + // + PciIoDevice->PciBar[BarIndex].Alignment =3D (SIZE_4KB - 1); + } else { + PciIoDevice->PciBar[BarIndex].Alignment =3D PciIoDevice->PciBar[Ba= rIndex].Length - 1; + } + break; + } + } + + // + // Check the length again so as to keep compatible with some special bar= s + // + 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, &gEdkiiDeviceIdentifierTypePci= Guid); + 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 (mDeviceSecurit= yProtocol, &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 privat= e 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_CA= PABILITY_DEVICE_CAPABILITIES_2_OFFSET, + 1, + &Data32 + ); + if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDI= NG) !=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_PCI= E_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->AriCa= pabilityOffset)); + } + } + + // + // 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 Hiera= rchy for the device. + // + if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != =3D 0) { + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABIL= ITY_ID_SRIOV_CONTROL, + 1, + &Data16 + ); + Data16 |=3D EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABIL= ITY_ID_SRIOV_CONTROL, + 1, + &Data16 + ); + } + + // + // Calculate SystemPageSize + // + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILIT= Y_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_CAPABILIT= Y_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_CAPABILIT= Y_ID_SRIOV_FIRSTVF, + 1, + &FirstVFOffset + ); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILIT= Y_ID_SRIOV_INITIALVFS, + 1, + &PciIoDevice->InitialVFs + ); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILIT= Y_ID_SRIOV_VFSTRIDE, + 1, + &VFStride + ); + // + // Calculate LastVF + // + PFRid =3D EFI_PCI_RID(Bus, Device, Func); + LastVF =3D PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * V= FStride; + + // + // 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; Fir= stVFOffset =3D 0x%x;\n", + SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffse= t + )); + DEBUG (( + EFI_D_INFO, + " InitialVFs =3D 0x%x; ReservedBusNum =3D 0x%x; CapOffset = =3D 0x%x\n", + PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice-= >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->Mr= IovCapabilityOffset)); + } + } + + 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 ResizableBar= Control; + UINT32 Offset; + Offset =3D PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXT= ENDED_CAPABILITIES_HEADER) + + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_= CAPABILITY), + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + Offset, + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONT= ROL), + &ResizableBarControl + ); + PciIoDevice->ResizableBarNumber =3D ResizableBarControl.Bits.Resizab= leBarNumber; + 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 bus = 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 successf= ully + // + 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 **) &D= escriptors); + + 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 bridge= 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 enumeration + // + 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 rejecte= d 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 * sizeo= f (UINT32)) { + + Mask =3D (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC; + Status =3D BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValu= e); + 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 (UIN= T32)) { + // + // 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, &OldV= alue); + 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, 0x18)= ; + 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/Pc= i/PciBusDxe/PciEnumeratorSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Over= ride/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h new file mode 100644 index 0000000000..1d39c5171d --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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_P= ROTOCOL. + @param Pci Output buffer for PCI device configuration spac= e. + @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 to = 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 inform= ation. + +**/ +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_ATTRI= BUTES. + +**/ +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 attribut= e. + @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back = 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 incompatibl= e PCI device. + + @param PciIoDevice Input Pci device instance. Output Pci device ins= tance 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 instance. + + @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 bus = 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 rejecte= d 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 reso= urces. +**/ +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/Pc= i/PciBusDxe/PciHotPlugSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Overrid= e/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c new file mode 100644 index 0000000000..d6d06b061a --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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_HP= C_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 structure. + @param DevicePath2 A pointer to the second device path data structure= . + + @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 protoco= l + to get PCI Hot Plug controller's information and constructor the root ho= t plug + private data structure. + + @retval EFI_SUCCESS They are same. + @retval EFI_UNSUPPORTED No PCI Hot Plug controller on the platform= . + @retval EFI_OUT_OF_RESOURCES No memory to constructor root hot plug pri= vate + 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) * gPciR= ootHpcCount); + 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 test= ed. + @param HpIndex If HpIndex is not NULL, return the index of root h= ot + 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, HpbDev= icePath)) { + + 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 test= ed. + @param HpIndex If HpIndex is not NULL, return the index of root h= ot + plug in global array when TRUE is returned. + + @retval TRUE The device path is for root pci hot plug controlle= r. + @retval FALSE The device path is not for root pci hot plug contr= oller. + +**/ +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, HpcDev= icePath)) { + + 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' in= itialization. + + @retval EFI_SUCCESS All HPCs initialization finished. + @retval EFI_TIMEOUT Not ALL HPCs initialization finished in Mi= croseconds. + +**/ +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].Initiali= zed) { + 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 block. + + @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 capability + register, + - and the device has the HotPlugCapable bit set in its slot capabilities + register. + + @param[in] PciIoDevice The device being checked. + + @retval TRUE PciIoDevice is a PCIe port that accepts a hot-plugged dev= ice. + @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->D= eviceNumber, 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_I= NITIALIZED) !=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 port,= 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/Pc= i/PciBusDxe/PciHotPlugSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Overrid= e/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h new file mode 100644 index 0000000000..0b69237a3d --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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_HP= C_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 structure. + @param DevicePath2 A pointer to the second device path data structure= . + + @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 protoco= l + to get PCI Hot Plug controller's information and constructor the root ho= t plug + private data structure. + + @retval EFI_SUCCESS They are same. + @retval EFI_UNSUPPORTED No PCI Hot Plug controller on the platform= . + @retval EFI_OUT_OF_RESOURCES No memory to constructor root hot plug pri= vate + 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 test= ed. + @param HpIndex If HpIndex is not NULL, return the index of root h= ot + 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 test= ed. + @param HpIndex If HpIndex is not NULL, return the index of root h= ot + plug in global array when TRUE is returned. + + @retval TRUE The device path is for root pci hot plug controlle= r. + @retval FALSE The device path is not for root pci hot plug contr= oller. + +**/ +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' in= itialization. + + @retval EFI_SUCCESS All HPCs initialization finished. + @retval EFI_TIMEOUT Not ALL HPCs initialization finished in Mi= croseconds. + +**/ +EFI_STATUS +AllRootHPCInitialized ( + IN UINTN TimeoutInMicroSeconds + ); + +/** + Check whether PCI-PCI bridge has PCI Hot Plug capability register block. + + @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 capability + register, + - and the device has the HotPlugCapable bit set in its slot capabilities + register. + + @param[in] PciIoDevice The device being checked. + + @retval TRUE PciIoDevice is a PCIe port that accepts a hot-plugged dev= ice. + @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/Pc= i/PciBusDxe/PciIo.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModuleP= kg/Bus/Pci/PciBusDxe/PciIo.c new file mode 100644 index 0000000000..c656056315 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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_PROTO= COL)); +} + +/** + Verifies access to a PCI Base Address Register (BAR). + + @param PciIoDevice Pci device instance. + @param BarIndex The BAR index of the standard PCI Configuration head= er to use as the + base address for the memory or I/O operation to perf= orm. + @param Type Operation type could be memory or I/O. + @param Width Signifies the width of the memory or I/O operations. + @param Count The number of memory or I/O operations to perform. + @param Offset The offset within the PCI configuration space for th= e 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 EfiPciIoWidthUintX + // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX + // + if (Width >=3D EfiPciIoWidthFifoUint8 && Width <=3D EfiPciIoWidthFifoUin= t64) { + 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 operations. + @param Count The number of memory or I/O operations to perform. + @param Offset The offset within the PCI configuration space for th= e 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 EfiPciIoWidthUintX + // + Width =3D (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03); + + if (PciIoDevice->IsPciExp) { + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >=3D PCI_EXP_MAX_CONFI= G_OFFSET) { + return EFI_UNSUPPORTED; + } + + ExtendOffset =3D LShiftU64 (*Offset, 32); + *Offset =3D EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice= ->DeviceNumber, PciIoDevice->FunctionNumber, 0); + *Offset =3D (*Offset) | ExtendOffset; + + } else { + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >=3D PCI_MAX_CONFIG_OF= FSET) { + return EFI_UNSUPPORTED; + } + + *Offset =3D EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->Devi= ceNumber, PciIoDevice->FunctionNumber, *Offset); + } + + return EFI_SUCCESS; +} + +/** + Reads from the memory space of a PCI controller. Returns either when the= polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param Offset The offset within the selected BAR to star= t the memory operation. + @param Mask Mask used for the polling criteria. + @param Value The comparison value used for the polling = exit criteria. + @param Delay The number of 100 ns units to poll. + @param Result Pointer to the last value read from the me= mory location. + + @retval EFI_SUCCESS The last data returned from the access mat= ched the poll exit criteria. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of th= is 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, W= idth, 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 EfiPciIoWithXXXUin= t8 + // + 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, Result= ); + 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_PROTOCO= L_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 the= polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param Offset The offset within the selected BAR to star= t the memory operation. + @param Mask Mask used for the polling criteria. + @param Value The comparison value used for the polling = exit criteria. + @param Delay The number of 100 ns units to poll. + @param Result Pointer to the last value read from the me= mory location. + + @retval EFI_SUCCESS The last data returned from the access mat= ched the poll exit criteria. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of th= is 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, Wi= dth, 1, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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, Result)= ; + 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_PROTOCO= L_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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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, W= idth, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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->PciRootBridgeIo= , + (EFI_PCI_ROOT_BRIDGE_IO_PROT= OCOL_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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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, W= idth, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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->PciRootBridgeIo= , + (EFI_PCI_ROOT_BRIDGE_IO_PROT= OCOL_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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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, Wi= dth, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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->PciRootBridgeIo= , + (EFI_PCI_ROOT_BRIDGE_IO_PROT= OCOL_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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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, Wi= dth, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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->PciRootBridgeIo= , + (EFI_PCI_ROOT_BRIDGE_IO_PROT= OCOL_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 configurat= ion space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory operatio= ns. + @param Offset The offset within the PCI configuration sp= ace for the PCI controller. + @param Count The number of PCI configuration operations= to perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = 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, &Add= ress); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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->PciRootBridgeI= o, + (EFI_PCI_ROOT_BRIDGE_IO_PRO= TOCOL_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 configurat= ion space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory operatio= ns. + @param Offset The offset within the PCI configuration sp= ace for the PCI controller. + @param Count The number of PCI configuration operations= to perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = 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, &Add= ress); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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->PciRootBridgeIo= , + (EFI_PCI_ROOT_BRIDGE_IO_PROT= OCOL_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 r= egion of PCI + memory space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory operatio= ns. + @param DestBarIndex The BAR index in the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param DestOffset The destination offset within the BAR spec= ified by DestBarIndex to + start the memory writes for the copy opera= tion. + @param SrcBarIndex The BAR index in the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param SrcOffset The source offset within the BAR specified= by SrcBarIndex to start + the memory reads for the copy operation. + @param Count The number of memory operations to perform= . Bytes moved is Width + size * Count, starting at DestOffset and S= rcOffset. + + @retval EFI_SUCCESS The data was copied from one memory region= to another memory region. + @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI contro= ller. + @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI control= ler. + @retval EFI_UNSUPPORTED The address range specified by DestOffset,= Width, and Count + is not valid for the PCI BAR specified by = DestBarIndex. + @retval EFI_UNSUPPORTED The address range specified by SrcOffset, = Width, and Count is + not valid for the PCI BAR specified by Src= BarIndex. + @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, PciBarTypeMe= m, Width, Count, &DestOffset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status =3D PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem= , Width, Count, &SrcOffset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // If request is not aligned, then convert request to EfiPciIoWithXXXUin= t8 + // + 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_PROTOCOL= _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 m= emory. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er 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 Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on 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 requ= ested 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 || DeviceAddres= s =3D=3D NULL || Mapping =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + RootBridgeIoOperation =3D (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Ope= ration; + 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_WR= ITE; + 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 insta= nce. + @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 s= ystem 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 EfiPciIoOperationBusMasterCommo= nBuffer + or EfiPciOperationBusMasterCommonBuffer64 mapping. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Type This parameter is not used and must be ign= ored. + @param MemoryType The type of memory to allocate, EfiBootSer= vicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param Attributes The requested bit mask of attributes for t= he allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU= AL_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 insta= nce. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated 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 syst= em memory. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + + @retval EFI_SUCCESS The PCI posted write transactions were flu= shed from the PCI host + bridge to system memory. + @retval EFI_DEVICE_ERROR The PCI posted write transactions were not= 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, a= nd function number. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param SegmentNumber The PCI controller's current PCI segment n= umber. + @param BusNumber The PCI controller's current PCI bus numbe= r. + @param DeviceNumber The PCI controller's current PCI device nu= mber. + @param FunctionNumber The PCI controller's current PCI function = 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 || Func= tion =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 hea= der to use as the + base address for the memory or I/O operation to per= form. + @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 BarTyp= e. + +**/ +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 attribu= te. + @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 & (~Attributes)= ; + } + + // + // 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 th= e 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 sno= op. + @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->Pare= ntHandle); + + 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 disabled + // + 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_SNOO= P); + 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 support= s. The operations include + getting the set of supported attributes, retrieving the current attribut= es, setting the current + attributes, enabling attributes, and disabling attributes. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Operation The operation to perform on the attributes= for this PCI controller. + @param Attributes The mask of attributes that are used for S= et, Enable, and Disable + operations. + @param Result A pointer to the result mask of attributes= that are returned for the Get + and Supported operations. + + @retval EFI_SUCCESS The operation on the PCI controller's attr= ibutes 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 c= ontroller 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 inter= nal usage. + // So, this logic doesn't conform to UEFI spec, which should be removed. + // But this trick logic is still kept for some binary drivers that depen= d 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_VG= A_PALETTE_IO)) !=3D 0) { + if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | EFI_PCI_IO_ATTRIBU= TE_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, Operat= ion); + 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_AT= TRIBUTE_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 Host = Bridge + // + Temp =3D LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo= ->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_AT= TRIBUTE_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 attributes + // 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 r= egister + // + Status =3D PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command); + if (BridgeControl !=3D 0) { + Status =3D PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeCo= ntrol); + } + + 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 control = register + // + Status =3D PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command); + if (BridgeControl !=3D 0) { + Status =3D PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeC= ontrol); + } + + 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 AddrTranslation= Offset + // is not zero, and device address =3D host address + AddrTranslationOff= set, 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->AddrTranslationOffse= t <=3D AddrRangeMin) && + (Configuration->AddrRangeMin + Configuration->AddrLen + Configurat= ion->AddrTranslationOffset >=3D AddrRangeMin + AddrLen) + ) { + return Configuration->AddrTranslationOffset; + } + Configuration++; + } + + // + // The resource occupied by BAR should be in the range reported by RootB= ridge. + // + ASSERT (FALSE); + return (UINT64) -1; +} + +/** + Gets the attributes that this PCI controller supports setting on a BAR u= sing + SetBarAttributes(), and retrieves the list of resource descriptors for a= BAR. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for resource range. The legal= range for this field is 0..5. + @param Supports A pointer to the mask of attributes that t= his PCI controller supports + setting for this BAR with SetBarAttributes= (). + @param Resources A pointer to the resource descriptors that= describe the current + configuration of this BAR of the PCI contr= oller. + + @retval EFI_SUCCESS If Supports is not NULL, then the attribut= es that the PCI + controller supports are returned in Suppor= ts. If Resources + is not NULL, then the resource descriptors= that the PCI + controller is currently using are returned= in Resources. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o 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].BarTyp= e =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_CACH= ED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; + } + + if (Resources !=3D NULL) { + Descriptor =3D AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRI= PTOR) + 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_PREFETCHABLE; + // + // 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_PREFETCHABLE; + // + // 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 GetMmioAddressTranslationOffse= t ( + 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 - tran= slation. + 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 insta= nce. + @param Attributes The mask of attributes to set for the reso= urce range specified by + BarIndex, Offset, and Length. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for resource range. The legal= range for this field is 0..5. + @param Offset A pointer to the BAR relative base address= of the resource range to be + modified by the attributes specified by At= tributes. + @param Length A pointer to the length of the resource ra= nge to be modified by the + attributes specified by Attributes. + + @retval EFI_SUCCESS The set of attributes specified by Attribu= tes for the resource + range specified by BarIndex, Offset, and L= ength were + set on the PCI controller, and the actual = 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 controller= . + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the = attributes on the + resource range specified by BarIndex, Offs= et, 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 B= arIndex, 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/Pc= i/PciBusDxe/PciIo.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModuleP= kg/Bus/Pci/PciBusDxe/PciIo.h new file mode 100644 index 0000000000..c00516ee6a --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 head= er to use as the + base address for the memory or I/O operation to perf= orm. + @param Type Operation type could be memory or I/O. + @param Width Signifies the width of the memory or I/O operations. + @param Count The number of memory or I/O operations to perform. + @param Offset The offset within the PCI configuration space for th= e 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 operations. + @param Count The number of memory or I/O operations to perform. + @param Offset The offset within the PCI configuration space for th= e 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 the= polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param Offset The offset within the selected BAR to star= t the memory operation. + @param Mask Mask used for the polling criteria. + @param Value The comparison value used for the polling = exit criteria. + @param Delay The number of 100 ns units to poll. + @param Result Pointer to the last value read from the me= mory location. + + @retval EFI_SUCCESS The last data returned from the access mat= ched the poll exit criteria. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of th= is 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 the= polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param Offset The offset within the selected BAR to star= t the memory operation. + @param Mask Mask used for the polling criteria. + @param Value The comparison value used for the polling = exit criteria. + @param Delay The number of 100 ns units to poll. + @param Result Pointer to the last value read from the me= mory location. + + @retval EFI_SUCCESS The last data returned from the access mat= ched the poll exit criteria. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of th= is 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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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 memory= or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory or I/O o= perations. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for the memory or I/O operati= on to perform. + @param Offset The offset within the selected BAR to star= t the memory or I/O operation. + @param Count The number of memory or I/O operations to = perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI BAR specified by BarInde= x. + @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 configurat= ion space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory operatio= ns. + @param Offset The offset within the PCI configuration sp= ace for the PCI controller. + @param Count The number of PCI configuration operations= to perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = 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 configurat= ion space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory operatio= ns. + @param Offset The offset within the PCI configuration sp= ace for the PCI controller. + @param Count The number of PCI configuration operations= to perform. + @param Buffer For read operations, the destination buffe= r to store the results. For write + operations, the source buffer to write dat= a from. + + + @retval EFI_SUCCESS The data was read from or written to the P= CI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = 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 r= egion of PCI + memory space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Width Signifies the width of the memory operatio= ns. + @param DestBarIndex The BAR index in the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param DestOffset The destination offset within the BAR spec= ified by DestBarIndex to + start the memory writes for the copy opera= tion. + @param SrcBarIndex The BAR index in the standard PCI Configur= ation header to use as the + base address for the memory operation to p= erform. + @param SrcOffset The source offset within the BAR specified= by SrcBarIndex to start + the memory reads for the copy operation. + @param Count The number of memory operations to perform= . Bytes moved is Width + size * Count, starting at DestOffset and S= rcOffset. + + @retval EFI_SUCCESS The data was copied from one memory region= to another memory region. + @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI contro= ller. + @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI control= ler. + @retval EFI_UNSUPPORTED The address range specified by DestOffset,= Width, and Count + is not valid for the PCI BAR specified by = DestBarIndex. + @retval EFI_UNSUPPORTED The address range specified by SrcOffset, = Width, and Count is + not valid for the PCI BAR specified by Src= BarIndex. + @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 m= emory. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er 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 Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on 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 requ= ested 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 insta= nce. + @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 s= ystem memory. + +**/ +EFI_STATUS +EFIAPI +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommo= nBuffer + or EfiPciOperationBusMasterCommonBuffer64 mapping. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Type This parameter is not used and must be ign= ored. + @param MemoryType The type of memory to allocate, EfiBootSer= vicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param Attributes The requested bit mask of attributes for t= he allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU= AL_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 insta= nce. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated 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 syst= em memory. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + + @retval EFI_SUCCESS The PCI posted write transactions were flu= shed from the PCI host + bridge to system memory. + @retval EFI_DEVICE_ERROR The PCI posted write transactions were not= 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, a= nd function number. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param SegmentNumber The PCI controller's current PCI segment n= umber. + @param BusNumber The PCI controller's current PCI bus numbe= r. + @param DeviceNumber The PCI controller's current PCI device nu= mber. + @param FunctionNumber The PCI controller's current PCI function = 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 hea= der to use as the + base address for the memory or I/O operation to per= form. + @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 BarTyp= e. + +**/ +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 attribu= te. + @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 sno= op. + @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 support= s. The operations include + getting the set of supported attributes, retrieving the current attribut= es, setting the current + attributes, enabling attributes, and disabling attributes. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param Operation The operation to perform on the attributes= for this PCI controller. + @param Attributes The mask of attributes that are used for S= et, Enable, and Disable + operations. + @param Result A pointer to the result mask of attributes= that are returned for the Get + and Supported operations. + + @retval EFI_SUCCESS The operation on the PCI controller's attr= ibutes 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 c= ontroller 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 u= sing + SetBarAttributes(), and retrieves the list of resource descriptors for a= BAR. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL insta= nce. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for resource range. The legal= range for this field is 0..5. + @param Supports A pointer to the mask of attributes that t= his PCI controller supports + setting for this BAR with SetBarAttributes= (). + @param Resources A pointer to the resource descriptors that= describe the current + configuration of this BAR of the PCI contr= oller. + + @retval EFI_SUCCESS If Supports is not NULL, then the attribut= es that the PCI + controller supports are returned in Suppor= ts. If Resources + is not NULL, then the resource descriptors= that the PCI + controller is currently using are returned= in Resources. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller= . + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o 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 insta= nce. + @param Attributes The mask of attributes to set for the reso= urce range specified by + BarIndex, Offset, and Length. + @param BarIndex The BAR index of the standard PCI Configur= ation header to use as the + base address for resource range. The legal= range for this field is 0..5. + @param Offset A pointer to the BAR relative base address= of the resource range to be + modified by the attributes specified by At= tributes. + @param Length A pointer to the length of the resource ra= nge to be modified by the + attributes specified by Attributes. + + @retval EFI_SUCCESS The set of attributes specified by Attribu= tes for the resource + range specified by BarIndex, Offset, and L= ength were + set on the PCI controller, and the actual = 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 controller= . + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the = attributes on the + resource range specified by BarIndex, Offs= et, 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/Pc= i/PciBusDxe/PciLib.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciLib.c new file mode 100644 index 0000000000..2b76100740 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 hierarch= y. + 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 Roo= t 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 (PcdPciBusHotplugDeviceSu= pport)) { + 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;\tAlignm= ent =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 : Resource-= >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->Alig= nment, + 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 < PP= B_IO_RANGE)) || + (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar = < 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;\tAlig= nment =3D 0x%lx", Resource->Length, Resource->Alignment)); + } + if (BridgeResource->ResType !=3D Resource->ResType) { + DEBUG ((EFI_D_INFO, "; Type =3D %s", mBarTypeStr[MIN (Resource->Re= sType, PciBarTypeMaxType)])); + } + DEBUG ((EFI_D_INFO, "\n")); + } + } +} + +/** + Find the corresponding resource node for the Device in child list of Bri= dgeResource. + + @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 for= 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[Index]= , NULL); + } + ChildResources =3D AllocatePool (sizeof (PCI_RESOURCE_NODE *) * Chil= dResourceCount); + ASSERT (ChildResources !=3D NULL); + ChildResourceCount =3D 0; + for (Index =3D 0; Index < ResourceCount; Index++) { + ChildResourceCount +=3D FindResourceNode (Device, Resources[Index]= , &ChildResources[ChildResourceCount]); + } + + DumpResourceMap (Device, ChildResources, ChildResourceCount); + FreePool (ChildResources); + } + } +} + +/** + Adjust the Devices' BAR size to minimum value if it support Resizeable B= AR 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->ChildLi= st) { + 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 && BarIndex= < 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 H= ost Bridge. + + @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RE= SOURCE_ALLOCATION_PROTOCOL. + + @retval EFI_SUCCESS Successfully finished resource allocation. + @retval EFI_NOT_FOUND Cannot get root bridge instance. + @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources i= f no hot plug supported. + @retval other Some error occurred when allocating resour= ces for the PCI Host Bridge. + + @note Feature flag PcdPciBusHotplugDeviceSupport determine whether nee= d 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 collec= ted 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: 0= xFFF, + 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 resou= rce 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, PMem3= 2Bridge, Mem64Bridge, PMem64Bridge); + } + + // + // Create resourcemap by going through all the devices subject to th= is root bridge + // + CreateResourceMap ( + RootBridgeDev, + IoBridge, + Mem32Bridge, + PMem32Bridge, + Mem64Bridge, + PMem64Bridge + ); + + // + // Based on the all the resource tree, construct ACPI resource node = 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, EfiPciHostBridgeAllocateResources= ); + 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 main = while + // + HandleExtendedData.Handle =3D RootBridgeDev->PciRootBridgeIo->Parent= Handle; + + 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 bri= dge + // + + 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, &RootBridgeHandl= e) =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->Pare= ntHandle; + + // + // 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 ad= justed, + // reject the device who requests largest resource that causes confli= ct. + // + 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 collecte= d 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 programm= ed. + // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Ba= se 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].Lengt= h + )); + ProcessOptionRom (RootBridgeDev, RootBridgeDev->PciBar[0].BaseAddress,= RootBridgeDev->PciBar[0].Length); + + IoBridge ->PciDev->PciBar[IoBridge ->Bar].BaseAddress =3D IoBase= ; + Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress =3D Mem32B= ase; + PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress =3D PMem32= Base; + Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress =3D Mem64B= ase; + PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress =3D PMem64= Base; + + // + // 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, EfiPciHostBridgeEndResourceAllocati= on); + + return Status; +} + +/** + Allocate NumberOfBuses buses and return the next available PCI bus numbe= r. + + @param Bridge Bridge device instance. + @param StartBusNumber Current available PCI bus number. + @param NumberOfBuses Number of buses enumerated below the StartBusNu= mber. + @param NextBusNumber Next available PCI bus number. + + @retval EFI_SUCCESS Available bus number resource is enough. N= ext available PCI bus number + is returned in NextBusNumber. + @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enoug= h 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 && StartBusNumbe= r <=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 + BusNumberRang= es->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 nee= d 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, &HpIndex)= ) { + 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].HpcDevi= cePath, + 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 bus = number padding requested. + // + return Status; + } + } + } + } + + Status =3D PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusN= umber); + if (EFI_ERROR (Status)) { + return Status; + } + SecondBus =3D *SubBusNumber; + + Register =3D (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber= ); + Address =3D EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_B= RIDGE_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 to = 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) + *PaddedBusRa= nge); + } else { + // + // Reserve the larger one between the actual occupied bus numb= er and padded bus number + // + Status =3D PciAllocateBusNumber (PciDevice, SecondBus, (UINT8)= (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_BRI= DGE_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 f= or one device + // + if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffs= et !=3D 0) { + if (TempReservedBusNum < PciDevice->ReservedBusNum) { + + Status =3D PciAllocateBusNumber (PciDevice, *SubBusNumber, (UI= NT8) (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 on = 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 (P= cdPciBusHotplugDeviceSupport)) { + + // + // 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->DeviceNumbe= r, 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_RESOURC= E_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 on = 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 proto= col. + + @retval EFI_SUCCESS Successfully enumerated the host bridge. + @retval EFI_OUT_OF_RESOURCES No enough memory available. + @retval other Some error occurred when enumerating the = 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, EfiPciHostBridgeBeginBusAllocation)= ; + + 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 i= t + // + + 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 (PcdPciBusHotplugDevice= Support)) { + 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 (PcdPciBusHotplugDeviceSu= pport)) { + // + // 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 time + // + Status =3D NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocatio= n); + + 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 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 + ); + + 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, EfiPciHostBridgeBeginResourceAlloca= tion); + + 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 i= t + // + 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 Pcihostbrid= ge + // protocol + // + DetermineRootBridgeAttributes ( + PciResAlloc, + RootBridgeDev + ); + + // + // Collect all the resource information under this root bridge + // A database that records all the information about pci device subjec= t 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 h= ost 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_C= APABILITIES_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 suppo= rts + // 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.Bar= SizeCapability, 28) + | Entries[Index].ResizableBarCapability.Bits.BarSizeCapa= bility; + + 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_EXTEN= DED_CAPABILITIES_HEADER) + + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_= BAR_ENTRY) + + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_E= NTRY, ResizableBarControl); + + Entries[Index].ResizableBarControl.Bits.BarSize =3D (UINT32) Bit; + DEBUG (( + DEBUG_INFO, + " Resizable Bar: Offset =3D 0x%x, Bar Size Capability =3D 0x%016lx= , 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/Pc= i/PciBusDxe/PciLib.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciLib.h new file mode 100644 index 0000000000..70ab07a8c3 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 H= ost Bridge. + + @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RE= SOURCE_ALLOCATION_PROTOCOL. + + @retval EFI_SUCCESS Successfully finished resource allocation. + @retval EFI_NOT_FOUND Cannot get root bridge instance. + @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources i= f no hot plug supported. + @retval other Some error occurred when allocating resour= ces for the PCI Host Bridge. + + @note Feature flag PcdPciBusHotplugDeviceSupport determine whether nee= d support hotplug. + +**/ +EFI_STATUS +PciHostBridgeResourceAllocator ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ); + +/** + Allocate NumberOfBuses buses and return the next available PCI bus numbe= r. + + @param Bridge Bridge device instance. + @param StartBusNumber Current available PCI bus number. + @param NumberOfBuses Number of buses enumerated below the StartBusNu= mber. + @param NextBusNumber Next available PCI bus number. + + @retval EFI_SUCCESS Available bus number resource is enough. N= ext available PCI bus number + is returned in NextBusNumber. + @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enoug= h 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 nee= d 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 on = 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_RESOURC= E_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 on = 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 proto= col. + + @retval EFI_SUCCESS Successfully enumerated the host bridge. + @retval EFI_OUT_OF_RESOURCES No enough memory available. + @retval other Some error occurred when enumerating the = 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 h= ost 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/Pc= i/PciBusDxe/PciOptionRomSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Overr= ide/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c new file mode 100644 index 0000000000..efdfa2d415 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 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_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 cu= rrent directory entry. + BufferSize has been updated with the size = 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 *) FilePa= th; + 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->StartingO= ffset + ); + 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_EFIS= IGNATURE) && + ((EfiRomHeader->EfiSubsystem =3D=3D EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SER= VICE_DRIVER) || + (EfiRomHeader->EfiSubsystem =3D=3D EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_= DRIVER)) && + (EfiRomHeader->CompressionType <=3D EFI_PCI_EXPANSION_ROM_HEADER_COM= PRESSED) + ) { + + ImageSize =3D Pcir->ImageLength * 512; + InitializationSize =3D (UINT32) EfiRomHeader->InitializationSize * 512= ; + if (InitializationSize > ImageSize || EfiRomHeader->EfiImageHeaderOffs= et >=3D InitializationSize) { + return EFI_NOT_FOUND; + } + + ImageBuffer =3D (UINT8 *) EfiRomHeader + EfiRomHeader->Efi= ImageHeaderOffset; + ImageLength =3D InitializationSize - EfiRomHeader->EfiImag= eHeaderOffset; + + if (EfiRomHeader->CompressionType !=3D EFI_PCI_EXPANSION_ROM_HEADER_CO= MPRESSED) { + // + // 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 with = a return + code of EFI_SUCCESS, the amount of data transferred t= o Buffer. + On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested= file. + @param Buffer The memory buffer to transfer the file to. If Buffer = 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 cu= rrent directory entry. + BufferSize has been updated with the size = 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 OptionRom = 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 + 51= 2); + 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_STR= UCTURE) > (UINT8 *) RomImage + RomSize) { + break; + } + + RomPcir =3D (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->P= cirOffset); + 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 + RomP= cir->ImageLength * 512); + } while (((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) && ((Indic= ator & 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 ima= ges 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 f= urther 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 *)R= omHeader)->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 m= aximum + // 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 SSVID = 0x15B3 and SSDID 0x0031 + if (PciDevice->Pci.Hdr.VendorId =3D=3D 0x15B3 && PciDevice->Pci.Hdr.Devi= ceId =3D=3D 0x1015) { + if (PciDevice->Pci.Device.SubsystemVendorID =3D=3D 0x15B3 && PciDevice= ->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 S= VID=3D%X, SVDID=3D%XOverrides ROM file @ %X size=3D%X .\n\n", + PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->Fun= ctionNumber, + PciDevice->Pci.Hdr.VendorId, PciDevice->Pci.Hdr.DeviceId, Pci= Device->Pci.Device.SubsystemVendorID,PciDevice->Pci.Device.SubsystemID,PciD= evice->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 enumerat= ion + // + 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 head= er to use as the + base address for resource range. The legal range for= 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 im= age. + @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->P= cirOffset); + 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_APPLICAT= ION) { + 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 (EfiOpRomIm= ageNode)); + EfiOpRomImageNode.StartingOffset =3D (UINTN) RomBarOffset - (UINTN) R= omBar; + EfiOpRomImageNode.EndingOffset =3D (UINTN) RomBarOffset + ImageSize= - 1 - (UINTN) RomBar; + + PciOptionRomImageDevicePath =3D AppendDevicePathNode (PciDevice->Devic= ePath, &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 usi= ng 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 - (U= INTN) RomBar) < PciDevice->RomSize)); + + return RetStatus; +} + diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/PciOptionRomSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Overr= ide/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h new file mode 100644 index 0000000000..60e147a7b9 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 with = a return + code of EFI_SUCCESS, the amount of data transferred t= o Buffer. + On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested= file. + @param Buffer The memory buffer to transfer the file to. If Buffer = 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 cu= rrent directory entry. + BufferSize has been updated with the size = 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 OptionRom = 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 head= er to use as the + base address for resource range. The legal range for= 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 im= age. + @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/Pc= i/PciBusDxe/PciPowerManagement.c b/Platform/Intel/PurleyOpenBoardPkg/Overri= de/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c new file mode 100644 index 0000000000..cf3f8164cd --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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/Pc= i/PciBusDxe/PciPowerManagement.h b/Platform/Intel/PurleyOpenBoardPkg/Overri= de/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h new file mode 100644 index 0000000000..44e97ec45a --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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/Pc= i/PciBusDxe/PciResourceSupport.c b/Platform/Intel/PurleyOpenBoardPkg/Overri= de/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c new file mode 100644 index 0000000000..1461af7d5d --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 ranges = 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 TempAlignR= est)) { + 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 thi= s 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 de= stination 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 (&(N= ode->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 alignment + // 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 r= esource. + // + 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->Ali= gnment + 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[PciResUsageTypica= l], Bridge->Alignment + 1); + Aperture[PciResUsagePadding] =3D ALIGN_VALUE (Aperture[PciResUsagePaddin= g], Bridge->Alignment + 1); + + // + // Hotplug controller needs padding resources. + // Use the larger one between the padding resource and actual occupied r= esource. + // + Bridge->Length =3D MAX (Aperture[PciResUsageTypical], Aperture[PciResUsa= gePadding]); + + // + // Adjust the bridge's alignment to the MAX (first) alignment of all chi= ldren. + // + 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, Re= sUsage); + 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 thi= s PPB + // Note: For PPB, memory aperture is aligned with 1MB and IO apertur= e + // 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 platform= . + + @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 its= PMEM64/MEM64 + // requests in case that if a legacy option ROM image can not access 6= 4-bit resources. + // + ChildDeviceLink =3D Bridge->ChildList.ForwardLink; + while (ChildDeviceLink !=3D NULL && ChildDeviceLink !=3D &Bridge->Chil= dList) { + 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[ResourceNod= e->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[ResourceNod= e->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_SUPP= ORTED)) { + MergeResourceTree ( + Mem32Node, + Mem64Node, + TRUE + ); + } + + // + // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUP= PORTED)) { + MergeResourceTree ( + PMem32Node, + PMem64Node, + TRUE + ); + } + + // + // if both PMEM64 and PMEM32 requests from child devices, which can no= t be satisfied + // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 to M= EM32. + // + if (!IsListEmpty (&PMem64Node->ChildList) && Bridge->Parent !=3D NULL)= { + MergeResourceTree ( + Mem32Node, + PMem32Node, + TRUE + ); + } + } + + // + // If bridge doesn't support Pmem32 + // degrade it to mem32 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPO= RTED)) { + 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_SUP= PORTED)) { + 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 PciResUsagePaddi= ng) { + // + // 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_TYPE01,= Bridge.MemoryBase), 1, &Base); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01,= 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 r= equire 32bit MMIO. + // + Base =3D (UINT16) gAllOne; + Limit =3D (UINT16) gAllZero; + } else { + Base =3D (UINT16) ((UINT32) Parent->PciBar[PPB_MEM32_RANGE].BaseA= ddress >> 16); + Limit =3D (UINT16) ((UINT32) (Parent->PciBar[PPB_MEM32_RANGE].Base= Address + + Parent->PciBar[PPB_MEM32_RANGE].Leng= th - 1) >> 16); + } + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01,= Bridge.MemoryBase), 1, &Base); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01,= 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_DES= CRIPTOR) { + + 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 (PcdPciBusHotplugDeviceSu= pport)) { + if (PciIoDevice->ResourcePaddingDescriptors =3D=3D NULL) { + GetResourcePaddingForHpb (PciIoDevice); + } + } +} + diff --git a/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pc= i/PciBusDxe/PciResourceSupport.h b/Platform/Intel/PurleyOpenBoardPkg/Overri= de/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h new file mode 100644 index 0000000000..2a33f77e55 --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 thi= s 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 de= stination 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 platform= . + + @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/Pc= i/PciBusDxe/PciRomTable.c b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeM= odulePkg/Bus/Pci/PciBusDxe/PciRomTable.c new file mode 100644 index 0000000000..507aed5cfe --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 passe= d 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_IMA= GE), + 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/Pc= i/PciBusDxe/PciRomTable.h b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeM= odulePkg/Bus/Pci/PciBusDxe/PciRomTable.h new file mode 100644 index 0000000000..fb356bd6de --- /dev/null +++ b/Platform/Intel/PurleyOpenBoardPkg/Override/MdeModulePkg/Bus/Pci/PciBu= sDxe/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 Please consider the environment before printing this email. The information contained in this message may be confidential and proprieta= ry 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 desig= nee. If the reader of this message is not the intended recipient, you are o= n notice that any distribution of this message, in any form, is strictly pr= ohibited. Please promptly notify the sender by reply e-mail or by telephon= e at 770-246-8600, and then delete or destroy all copies of the transmissio= n. GitPatchExtractor 1.1 --_004_PH0PR10MB440879FF835AAF41937C1185BB0E9PH0PR10MB4408namp_--