Topics

[PATCH v2 1/2] OvmfPkg/IntelGvtGopDxe: Intel GVT-g GOP Implementation.


Colin Xu
 

SW50ZWwgR1ZULWcgR09QIERYRSBzdXBwb3J0cyBPVk1GIEdPUCBvdXRwdXQgaXRzIGZyYW1lIGJ1
ZmZlciB0byB2R1BVCnBhcnRpdGlvbmVkIGFwZXJ0dXJlIG1hcHBlZCBieSBHR1RULCBzbyB0aGF0
IHRoZSBHT1Agb3V0cHV0IGNhbiBiZQptZWRpYXRlZCB0byBpdHMgYmFja2VuZCBmb3IgZGlzcGxh
eSAoaS5lLiBRRU1VIEdUSyBkaXNwbGF5IHZpYSBkbWEtYnVmKS4KClVubGlrZSBBQ1JOIEdWVC1k
IGludGVncmF0aW5nIG5hdGl2ZSBHT1AvVkJUIGludG8gaXQncyBPVk1GLCB0aGUgR1ZULWcKR09Q
IGlzIGFuIG9wZW4tc291cmNlIGltcGxlbWVudGF0aW9uIHdoaWNoIGZvbGxvd3MgSW50ZWwgR1ZU
LWcgZnJhbWV3b3JrCnRvIGludGVyYWN0IHdpdGggS1ZNR1QgaW4gaG9zdCBrZXJuZWwgc28gdGhh
dCB0aGUgR09QIGZyYW1lIGJ1ZmZlcgpjb250ZW50IGNhbiBiZSBwcm9jZXNzZWQgcHJvcGVybHku
CgpXaXRoIEdWVC1nIEdPUCBlbmFibGVkIE9WTUYsIGd1ZXN0IFZNIGNhbiBvdXRwdXQgaXRzIGZy
YW1lYnVmZmVyCmNvbnRlbnQgdG8gS1ZNR1QgdmlhIEdPUCwgd2l0aCBhIHByb3BlciBiYWNrZW5k
IHN1cHBvcnQgKGkuZS4gUUVNVSBHVEsKZGlzcGxheSB3aXRoIGRtYS1idWYpLCB0aGUgZm9sbG93
aW5nIGNvbnRlbnQgaXMgbm93IGRpcmVjdGx5IHZpc2libGUgdG8KdXNlciB1bmxpa2UgcHJldmlv
c2x5IG5lZWQgYSBzZWNvbmQgR1BVOgotIE9WTUYgRUZJIFNoZWxsCi0gQm9vdGxvYWRlciAoaS5l
LiBncnViKQotIE9TIGluc3RhbGxhdGlvbiBwcm9ncmVzcy4gKGJlZm9yZSBidWlsdC1pbiBHRlgg
ZHJpdmVyIGxvYWRlZCkKLSBQcmUgR0ZYIERyaXZlciBkaXNwbGF5IChpLmUuIEFuZHJvaWQvTGlu
dXggYm9vdCBzcGxhc2ggb3IgbG9nbywKICBXaW5kb3dzIDguMSBib290IHByb2dyZXNzL3NhZmUg
bW9kZS9yZWNvdmVyeSBtb2RlL0JTT0QvR1BVLWRpc2FibGVkCiAgZGVza3RvcCwgZXRjLikKCkdW
VC1nIEdPUCBoYXMgYmVsb3cgY2FwYWJpbGl0ZXM6Ci0gQ2hlY2sgR1ZULWcgY29tcGF0aWJpbGl0
eSB2aWEgUFYgaW5mbywgb25seSBlbmFibGUgR1ZULWcgR09QIHdoZW4gaXQncwogIGNvbXBhdGli
bGUgd2l0aCBLVk1HVC4KLSBSL1cgTU1JTyBmcm9tIEJBUjAuCi0gUi9XIEdsb2JhbCBHVFQgZnJv
bSBCQVIwLgotIFJlc2VydmUgYW5kIHByb2dyYW0gT3BSZWdpb24gYWRkcmVzcyBhdCBBU0xTIGxv
Y2F0aW9uIHNvIHRoYXQgZ3Vlc3QKICBkcml2ZXIgY2FuIGRlY29kZSBHVlQtZyBzaW1sdWF0ZWQg
VkJUIGFuZCBlbmFibGVkIGRpc3BsYXkgcHJvcGVybHkuCi0gUmVzZXJ2ZSBndWVzdCBtZW1vcnkg
YW5kIG1hcCB0byBCQVIyIHBhcnRpdGlvbmVkIHJhbmdlIHdpdGggcHJvcGVyCiAgR0dUVCwgc28g
dGhhdCBLVk1HVCBjYW4gYWNjZXNzIHZpYSBwcm9wZXIgZ3Vlc3QgR1RUIHRvIGhvc3QgR0dUVCBt
YXAuCi0gQWxsIHN1cHBvcnRlZCBFRklfR1JBUEhJQ1NfT1VUUFVUX0JMVF9PUEVSQVRJT04gZnJv
bS90byB2aWRlbyBtZW1vcnkuCi0gRW5hYmxlL2Rpc2FibGUgR09QIGNvbnRlbnQgb24gUElQRV9B
LCBQTEFORV9QUklNQVJZIHdpdGggcHJvcGVyIHNjYWxpbmcuCi0gVkJFIFNoaW0gc28gdGhhdCBz
b21lIE9TIGNhbiBxdWVyeSBub24tZW1wdHkgbW9kZSBpbmZvIHZpYSBJTlQxMCBjYWxsCiAgdG8g
ZW5hYmxlIHRoZSBkZXNrdG9wIHdoZW4gR1BVIGlzIGRpc2FibGVkLgoKVjI6ClByb2dyYW0gUElQ
RVNSQyB0byBtYXRjaCBhY3RpdmUgSC9WLgoKU2lnbmVkLW9mZi1ieTogQ29saW4gWHUgPGNvbGlu
Lnh1QGludGVsLmNvbT4KLS0tCiBPdm1mUGtnL0ludGVsR3Z0R29wRHhlL0NvbW1vbi5oICAgICAg
ICAgICB8ICAgNDUgKwogT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9EZWJ1Z0hlbHBlci5oICAgICAg
fCAgIDIwICsKIE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvRGlzcGxheS5jICAgICAgICAgIHwgMTA3
NyArKysrKysrKysrKysrKysrKysrKysKIE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvRGlzcGxheS5o
ICAgICAgICAgIHwgIDE0MSArKysKIE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvR29wRHJpdmVyLmMg
ICAgICAgIHwgIDQ3OCArKysrKysrKysKIE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvR3B1UmVnLmMg
ICAgICAgICAgIHwgICA5MSArKwogT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9HcHVSZWcuaCAgICAg
ICAgICAgfCAgMTc1ICsrKysKIE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvR3R0LmMgICAgICAgICAg
ICAgIHwgIDE2MiArKysrCiBPdm1mUGtnL0ludGVsR3Z0R29wRHhlL0d0dC5oICAgICAgICAgICAg
ICB8ICAgNTEgKwogT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9JbnRlbEd2dEdvcER4ZS5pbmYgfCAg
IDU5ICsrCiBPdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZiZVNoaW0uYXNtICAgICAgICB8ICAzNDMg
KysrKysrKwogT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9WYmVTaGltLmMgICAgICAgICAgfCAgMjU4
ICsrKysrCiBPdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZiZVNoaW0uaCAgICAgICAgICB8ICA5MTIg
KysrKysrKysrKysrKysrKysKIE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmJlU2hpbS5zaCAgICAg
ICAgIHwgICA4MSArKwogT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9WaXJ0dWFsR3B1LmMgICAgICAg
fCAgNDAwICsrKysrKysrCiBPdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZpcnR1YWxHcHUuaCAgICAg
ICB8ICAgNTIgKwogMTYgZmlsZXMgY2hhbmdlZCwgNDM0NSBpbnNlcnRpb25zKCspCiBjcmVhdGUg
bW9kZSAxMDA2NDQgT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9Db21tb24uaAogY3JlYXRlIG1vZGUg
MTAwNjQ0IE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvRGVidWdIZWxwZXIuaAogY3JlYXRlIG1vZGUg
MTAwNjQ0IE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvRGlzcGxheS5jCiBjcmVhdGUgbW9kZSAxMDA2
NDQgT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9EaXNwbGF5LmgKIGNyZWF0ZSBtb2RlIDEwMDY0NCBP
dm1mUGtnL0ludGVsR3Z0R29wRHhlL0dvcERyaXZlci5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgT3Zt
ZlBrZy9JbnRlbEd2dEdvcER4ZS9HcHVSZWcuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IE92bWZQa2cv
SW50ZWxHdnRHb3BEeGUvR3B1UmVnLmgKIGNyZWF0ZSBtb2RlIDEwMDY0NCBPdm1mUGtnL0ludGVs
R3Z0R29wRHhlL0d0dC5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgT3ZtZlBrZy9JbnRlbEd2dEdvcER4
ZS9HdHQuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvSW50ZWxH
dnRHb3BEeGUuaW5mCiBjcmVhdGUgbW9kZSAxMDA2NDQgT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9W
YmVTaGltLmFzbQogY3JlYXRlIG1vZGUgMTAwNjQ0IE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmJl
U2hpbS5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9WYmVTaGlt
LmgKIGNyZWF0ZSBtb2RlIDEwMDc1NSBPdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZiZVNoaW0uc2gK
IGNyZWF0ZSBtb2RlIDEwMDY0NCBPdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZpcnR1YWxHcHUuYwog
Y3JlYXRlIG1vZGUgMTAwNjQ0IE92bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmlydHVhbEdwdS5oCgpk
aWZmIC0tZ2l0IGEvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9Db21tb24uaCBiL092bWZQa2cvSW50
ZWxHdnRHb3BEeGUvQ29tbW9uLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAw
MDAwLi5jZjMwNzUyZWI4ZjMKLS0tIC9kZXYvbnVsbAorKysgYi9Pdm1mUGtnL0ludGVsR3Z0R29w
RHhlL0NvbW1vbi5oCkBAIC0wLDAgKzEsNDUgQEAKKy8qKiBAZmlsZQ0KKyAgQ29tcG9uZW50IG5h
bWUgZm9yIHRoZSBRRU1VIHZpZGVvIGNvbnRyb2xsZXIuDQorDQorICBDb3B5cmlnaHQgKGMpIDIw
MjEsIEludGVsIENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLjxCUj4NCisNCisgIFNQ
RFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMi1DbGF1c2UtUGF0ZW50DQorDQorKiovDQorDQor
I2lmbmRlZiBfX0NPTU1PTl9IXw0KKw0KKyNpbmNsdWRlIDxQcm90b2NvbC9QY2lJby5oPg0KKyNp
bmNsdWRlIDxQcm90b2NvbC9EZXZpY2VQYXRoLmg+DQorI2luY2x1ZGUgPFByb3RvY29sL0dyYXBo
aWNzT3V0cHV0Lmg+DQorDQorI2luY2x1ZGUgPExpYnJhcnkvQmFzZUxpYi5oPg0KKyNpbmNsdWRl
IDxMaWJyYXJ5L1BjZExpYi5oPg0KKyNpbmNsdWRlIDxMaWJyYXJ5L1VlZmlMaWIuaD4NCisjaW5j
bHVkZSA8TGlicmFyeS9VZWZpRHJpdmVyRW50cnlQb2ludC5oPg0KKyNpbmNsdWRlIDxMaWJyYXJ5
L1VlZmlCb290U2VydmljZXNUYWJsZUxpYi5oPg0KKyNpbmNsdWRlIDxMaWJyYXJ5L0Jhc2VNZW1v
cnlMaWIuaD4NCisjaW5jbHVkZSA8TGlicmFyeS9NZW1vcnlBbGxvY2F0aW9uTGliLmg+DQorI2lu
Y2x1ZGUgPExpYnJhcnkvRGV2aWNlUGF0aExpYi5oPg0KKw0KKyNpbmNsdWRlIDxJbmR1c3RyeVN0
YW5kYXJkL1BjaS5oPg0KKw0KKyNpbmNsdWRlICJEZWJ1Z0hlbHBlci5oIg0KKw0KKyNkZWZpbmUg
SVNfQUxJR05FRChhZGRyLCBzaXplKSAoKChVSU5UTikgKGFkZHIpICYgKHNpemUgLSAxKSkgPT0g
MCkNCisNCit0eXBlZGVmIHN0cnVjdCB7DQorICBVSU5UNjQgICAgICAgICAgICAgICAgICAgICAg
IFNpZ25hdHVyZTsNCisgIEVGSV9IQU5ETEUgICAgICAgICAgICAgICAgICAgSGFuZGxlOw0KKyAg
RUZJX1BDSV9JT19QUk9UT0NPTCAgICAgICAgICAqUGNpSW87DQorICBVSU5UNjQgICAgICAgICAg
ICAgICAgICAgICAgIE9yaWdpbmFsUGNpQXR0cjsNCisgIEVGSV9HUkFQSElDU19PVVRQVVRfUFJP
VE9DT0wgR3JhcGhpY3NPdXRwdXRQcm90b2NvbDsNCisgIEVGSV9ERVZJQ0VfUEFUSF9QUk9UT0NP
TCAgICAgKkdvcERldlBhdGg7DQorICBWT0lEICAgICAgICAgICAgICAgICAgICAgICAgICpWaXJ0
dWFsR3B1Ow0KK30gR1ZUX0dPUF9QUklWQVRFX0RBVEE7DQorDQorI2RlZmluZSBHVlRfR09QX01B
R0lDICAgICAgICAgICAgICAgICAgICAgU0lHTkFUVVJFXzY0KCdHJywnVicsJ1QnLCdHJywnVics
J0cnLCdPJywnUCcpDQorI2RlZmluZSBHVlRfR09QX1BSSVZBVEVfREFUQV9GUk9NX1RISVMoYSkg
Q1IoYSwgR1ZUX0dPUF9QUklWQVRFX0RBVEEsIEdyYXBoaWNzT3V0cHV0UHJvdG9jb2wsIEdWVF9H
T1BfTUFHSUMpDQorDQorI2RlZmluZSBfX0NPTU1PTl9IXw0KKyNlbmRpZiAvL19fQ09NTU9OX0hf
DQpkaWZmIC0tZ2l0IGEvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9EZWJ1Z0hlbHBlci5oIGIvT3Zt
ZlBrZy9JbnRlbEd2dEdvcER4ZS9EZWJ1Z0hlbHBlci5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0Cmlu
ZGV4IDAwMDAwMDAwMDAwMC4uNzUxNThkNzEzZWMzCi0tLSAvZGV2L251bGwKKysrIGIvT3ZtZlBr
Zy9JbnRlbEd2dEdvcER4ZS9EZWJ1Z0hlbHBlci5oCkBAIC0wLDAgKzEsMjAgQEAKKy8qKiBAZmls
ZQ0KKyAgQ29tcG9uZW50IG5hbWUgZm9yIHRoZSBRRU1VIHZpZGVvIGNvbnRyb2xsZXIuDQorDQor
ICBDb3B5cmlnaHQgKGMpIDIwMjEsIEludGVsIENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2Vy
dmVkLjxCUj4NCisNCisgIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMi1DbGF1c2UtUGF0
ZW50DQorDQorKiovDQorDQorI2lmbmRlZiBfX0RFQlVHSEVMUEVSX0hfDQorI2RlZmluZSBfX0RF
QlVHSEVMUEVSX0hfDQorDQorI2luY2x1ZGUgPExpYnJhcnkvRGVidWdMaWIuaD4NCisNCisjZGVm
aW5lIEdWVF9ERUJVRyhFcnJMZXZlbCwgRm10LCBBcmdzLi4uKSBcDQorICBkbyB7IFwNCisgICAg
REVCVUcgKChFcnJMZXZlbCwgIkd2dEdvcDogIkZtdCwgIyNBcmdzKSk7XA0KKyAgfSB3aGlsZSAo
RkFMU0UpDQorDQorI2VuZGlmIC8vX19ERUJVR0hFTFBFUl9IXw0KZGlmZiAtLWdpdCBhL092bWZQ
a2cvSW50ZWxHdnRHb3BEeGUvRGlzcGxheS5jIGIvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9EaXNw
bGF5LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi4xMzNkZTI1ZmYw
M2MKLS0tIC9kZXYvbnVsbAorKysgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL0Rpc3BsYXkuYwpA
QCAtMCwwICsxLDEwNzcgQEAKKy8qKiBAZmlsZQ0KKyAgQ29tcG9uZW50IG5hbWUgZm9yIHRoZSBR
RU1VIHZpZGVvIGNvbnRyb2xsZXIuDQorDQorICBDb3B5cmlnaHQgKGMpIDIwMjEsIEludGVsIENv
cnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLjxCUj4NCisNCisgIFNQRFgtTGljZW5zZS1J
ZGVudGlmaWVyOiBCU0QtMi1DbGF1c2UtUGF0ZW50DQorDQorKiovDQorDQorI2luY2x1ZGUgIkNv
bW1vbi5oIg0KKyNpbmNsdWRlICJEaXNwbGF5LmgiDQorI2luY2x1ZGUgIkdwdVJlZy5oIg0KKyNp
bmNsdWRlICJHdHQuaCINCisjaW5jbHVkZSAiVmlydHVhbEdwdS5oIg0KKw0KK0VGSV9TVEFUVVMN
CitJbnRlbFZpcnR1YWxHcHVEaXNwbGF5SW5pdCAoDQorICBJTiBPVVQgR1ZUX0dPUF9QUklWQVRF
X0RBVEEgKlByaXZhdGUNCisgICkNCit7DQorICBFRklfU1RBVFVTICAgICAgICAgICAgICAgICBT
dGF0dXMgPSBFRklfVU5TVVBQT1JURUQ7DQorICBQSU5URUxfVklSVFVBTF9HUFUgICAgICAgICBW
aXJ0dWFsR3B1Ow0KKyAgUElOVEVMX1ZJUlRVQUxfR1BVX0RJU1BMQVkgRGlzcGxheTsNCisgIFVJ
TlQzMiAgICAgICAgICAgICAgICAgICAgIFZhbDMyOw0KKyAgVUlOVE4gICAgICAgICAgICAgICAg
ICAgICAgV2lkdGgsIEhlaWdodCwgTW9kZU51bWJlcjsNCisgIEVGSV9UUEwgICAgICAgICAgICAg
ICAgICAgIE9yaWdpbmFsVFBMOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWE6
ID4+PlxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIFZpcnR1YWxHcHUgPSAoUElOVEVMX1ZJUlRV
QUxfR1BVKVByaXZhdGUtPlZpcnR1YWxHcHU7DQorICBEaXNwbGF5ID0gJlZpcnR1YWxHcHUtPkRp
c3BsYXk7DQorDQorICAvKg0KKyAgICogSWYgUGNkVmlkZW9Ib3Jpem9udGFsUmVzb2x1dGlvbiBv
ciBQY2RWaWRlb1ZlcnRpY2FsUmVzb2x1dGlvbiBpcyBub3Qgc2V0LA0KKyAgICogICBHT1Agd2ls
bCBxdWVyeSB0aGUgbW9kZSBsaXN0IHJlcG9ydGVkIHRvIGZpbmQgdGhlIGhpZ2hlc3QgcmVzb2x1
dGlvbi4NCisgICAqICAgT3RoZXJ3aXNlLCBjaGVjayBpZiB0aGUgc2V0IFBjZFZpZGVvKlJlc29s
dXRpb24gaXMgZGVmaW5lZC4NCisgICAqICAgSWYgbm90IHN1cHBvcnRlZCwgdHJ5IDgwMHg2MDAg
d2hpY2ggaXMgcmVxdWlyZWQgYnkgVUVGSS9FRkkgc3BlYy4NCisgICAqICAgSWYgc3RpbGwgbm90
IHN1cHBvcnRlZCwgdXNlIHRoZSAxc3QgbW9kZSBpbiBtb2RlIGxpc3QuDQorICAgKiBJZiB0aGVy
ZSBhcmUgbXVsdGlwbGUgdmlkZW8gZGV2aWNlcywgZ3JhcGhpYyBjb25zb2xlIGRyaXZlciB3aWxs
IHNldCBhbGwNCisgICAqICAgdGhlIHZpZGVvIGRldmljZXMgdG8gdGhlIHNhbWUgbW9kZS4NCisg
ICAqIEFjY29yZGluZyB0byBVRUZJL0VGSSBzcGVjLCBpbiBhZGRpdGlvbiB0byBwbGF0Zm9ybSBk
ZXNpZ24gZ3VpZGUsIG9uLWJvYXJkDQorICAgKiAgIGdyYXBoaWNzIHNob3VsZCBzdXBwb3J0IG5h
dGl2ZSBtb2RlIG9mIHRoZSBkaXNwbGF5LCBwbHVnLWluIGdyYXBoaWNzDQorICAgKiAgIHNob3Vs
ZCBzdXBwb3J0IDgwMHg2MDB4MzIgb3IgNjQweDQ4MHgzMi4NCisgICAqIEFjY29yZGluZyB0byBz
b21lIE9TIHJlcXVpcmVtZW50IChpLmUuIFVFRkkgcmVxdWlybWVudCBmb3IgV2luZG93cyAxMCks
DQorICAgKiAgIGludGVncmF0ZWQgZGlzcGxheXMgc2hvdWxkIHN1cHBvcnQgcGFuZWwgbmF0aXZl
IHJlc29sdXRpb24gYW5kIGV4dGVybmFsDQorICAgKiAgIGRpc3BsYXlzIHNob3VsZCBzdXBwb3J0
IHRoZSBtYXhpbXVtIHJlc29sdXRpb24gb2YgYm90aCBHUFUgYW5kIGRpc3BsYXkgaW4NCisgICAq
ICAgR09QLiBGb3IgYWx0ZXJuYXRlIGRpc3BsYXkgb3V0cHV0LCBpdCBzaG91bGQgc3VwcG9ydCBu
YXRpdmUgb3IgaGlnaGVzdA0KKyAgICogICBjb21wYXRpYmxlIHJlc29sdXRpb24sIG90aGVyd2lz
ZSBzdXBwb3J0IGFuIGtub3duIG1vZGUgdG8gYmUgY29tcGF0aWJsZQ0KKyAgICogICB3aXRoIGFz
IG1hbnkgbW9uaXRvcnMgYXMgcG9zc2libGUgKDY0MHg0ODAsIDEwMjR4NzY4KS4NCisgICAqIER1
ZSB0byBhYm92ZSByZXF1aXJlbWVudCwgdXNlIG5hdGl2ZSByZXNvbHV0aW9uIGlmIFBjZFZpZGVv
KlJlc29sdXRpb24gaXMNCisgICAqICAgbm90IGRlZmluZWQuIFRvIHJlZHVjZSBHR1RUIHdyaXRl
IG92ZXJoZWFkLCBhbHNvIGxpbWl0IHRoZSBtYXhpbXVtIHRvDQorICAgKiAgIERJU1BMQVlfV0lE
VEhfTUFYL0RJU1BMQVlfSEVJR0hUX01BWC4NCisgICAqLw0KKw0KKyAgUmVnUmVhZDMyIChQcml2
YXRlLCBIVE9UQUwoUElQRV9BKSwgJlZhbDMyKTsNCisgIERpc3BsYXktPkhBY3RpdmUgPSAoVmFs
MzIgJiAweEZGRikgKyAxOw0KKyAgUmVnUmVhZDMyIChQcml2YXRlLCBWVE9UQUwoUElQRV9BKSwg
JlZhbDMyKTsNCisgIERpc3BsYXktPlZBY3RpdmUgPSAoVmFsMzIgJiAweEZGRikgKyAxOw0KKw0K
KyAgaWYgKERpc3BsYXktPkhBY3RpdmUgIT0gMCAmJiBEaXNwbGF5LT5WQWN0aXZlICE9IDApIHsN
CisgICAgV2lkdGggPSBEaXNwbGF5LT5IQWN0aXZlOw0KKyAgICBIZWlnaHQgPSBEaXNwbGF5LT5W
QWN0aXZlOw0KKyAgICBpZiAoRGlzcGxheS0+SEFjdGl2ZSA+IERJU1BMQVlfV0lEVEhfTUFYIHx8
DQorICAgICAgICBEaXNwbGF5LT5WQWN0aXZlID4gRElTUExBWV9IRUlHSFRfTUFYKSB7DQorICAg
ICAgV2lkdGggPSBESVNQTEFZX1dJRFRIX01BWDsNCisgICAgICBIZWlnaHQgPSBESVNQTEFZX0hF
SUdIVF9NQVg7DQorICAgIH0NCisgIH0gZWxzZSB7DQorICAgIFdpZHRoID0gRElTUExBWV9XSURU
SF9ERUZBVUxUOw0KKyAgICBIZWlnaHQgPSBESVNQTEFZX0hFSUdIVF9ERUZBVUxUOw0KKyAgfQ0K
Kw0KKyAgRGlzcGxheS0+V2lkdGggPSBXaWR0aDsNCisgIERpc3BsYXktPkhlaWdodCA9IEhlaWdo
dDsNCisgIERpc3BsYXktPkZvcm1hdCA9IFBpeGVsQmx1ZUdyZWVuUmVkUmVzZXJ2ZWQ4Qml0UGVy
Q29sb3I7DQorICBEaXNwbGF5LT5CcHAgPSA0Ow0KKyAgRGlzcGxheS0+TWF4TW9kZSA9IDE7DQor
DQorICAvLyBBZGQgZGVmYXVsdCBpZiBkZWZpbmVkDQorICBpZiAoUGNkR2V0MzIgKFBjZFZpZGVv
SG9yaXpvbnRhbFJlc29sdXRpb24pICE9IDAgJiYNCisgICAgICBQY2RHZXQzMiAoUGNkVmlkZW9W
ZXJ0aWNhbFJlc29sdXRpb24pICE9IDAgJiYNCisgICAgICBQY2RHZXQzMiAoUGNkVmlkZW9Ib3Jp
em9udGFsUmVzb2x1dGlvbikgIT0gV2lkdGggJiYNCisgICAgICBQY2RHZXQzMiAoUGNkVmlkZW9W
ZXJ0aWNhbFJlc29sdXRpb24pICE9IEhlaWdodCkgew0KKyAgICAgICsrRGlzcGxheS0+TWF4TW9k
ZTsNCisgIH0NCisNCisgIERpc3BsYXktPkN1cnJlbnRNb2RlID0gRElTUExBWV9NT0RFX0lOVkFM
SUQ7DQorICBEaXNwbGF5LT5GcmFtZUJ1ZmZlckJsdENvbmZpZ3VyZSA9IE5VTEw7DQorICBEaXNw
bGF5LT5GcmFtZUJ1ZmZlckJsdENvbmZpZ3VyZVNpemUgPSAwOw0KKw0KKyAgLy8gTGluZWFyIG11
c3Qgc3RhcnQgYXQgMjU2Sywgc3RyaWRlIGFsaWduIGF0IDY0DQorICBEaXNwbGF5LT5XaWR0aEJ5
dGVzID0gRGlzcGxheS0+V2lkdGggKiBEaXNwbGF5LT5CcHA7DQorICBEaXNwbGF5LT5TdHJpZGVC
eXRlcyA9IEFMSUdOX1ZBTFVFIChEaXNwbGF5LT5XaWR0aEJ5dGVzLCA2NCk7DQorICBEaXNwbGF5
LT5GYlNpemUgPSBEaXNwbGF5LT5TdHJpZGVCeXRlcyAqIERpc3BsYXktPkhlaWdodDsNCisgIERp
c3BsYXktPlBhZ2VzID0gRUZJX1NJWkVfVE9fUEFHRVMgKERpc3BsYXktPkZiU2l6ZSk7DQorDQor
ICBEaXNwbGF5LT5GYkdNQWRkciA9IFZpcnR1YWxHcHUtPkdwdU1lbUFkZHIgKyBWaXJ0dWFsR3B1
LT5WaXNpYmxlT2Zmc2V0Ow0KKyAgRGlzcGxheS0+RmJHTUFkZHIgPSBBTElHTl9WQUxVRSAoRGlz
cGxheS0+RmJHTUFkZHIsIFNJWkVfMjU2S0IpOw0KKw0KKyAgU3RhdHVzID0gZ0JTLT5BbGxvY2F0
ZVBhZ2VzICgNCisgICAgICAgICAgICAgICAgQWxsb2NhdGVBbnlQYWdlcywNCisgICAgICAgICAg
ICAgICAgRWZpUmVzZXJ2ZWRNZW1vcnlUeXBlLA0KKyAgICAgICAgICAgICAgICBEaXNwbGF5LT5Q
YWdlcywNCisgICAgICAgICAgICAgICAgJkRpc3BsYXktPkZiUGh5c2ljYWxBZGRyDQorICAgICAg
ICAgICAgICAgICk7DQorICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgIEdWVF9ERUJV
RyAoRUZJX0RfRVJST1IsDQorICAgICAgIkFsbG9jYXRlUGFnZXMgZmFpbGVkIGZvciBkaXNwbGF5
IEZCLCBwYWdlcyAlZCwgc2l6ZSAlbHgsIHN0YXR1cyAlZFxuIiwNCisgICAgICBEaXNwbGF5LT5Q
YWdlcywgRGlzcGxheS0+RmJTaXplLCBTdGF0dXMNCisgICAgICApOw0KKyAgICByZXR1cm4gU3Rh
dHVzOw0KKyAgfQ0KKw0KKyAgU3RhdHVzID0gVXBkYXRlR0dUVCAoUHJpdmF0ZSwNCisgICAgICAg
ICAgICAgRGlzcGxheS0+RmJHTUFkZHIsDQorICAgICAgICAgICAgIERpc3BsYXktPkZiUGh5c2lj
YWxBZGRyLA0KKyAgICAgICAgICAgICBEaXNwbGF5LT5QYWdlcw0KKyAgICAgICAgICAgICApOw0K
KyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9S
LA0KKyAgICAgICJGYWlsIHRvIFVwZGF0ZSBHR1RUIGZvciBkaXNwbGF5LCBzdGF0dXMgJWRcbiIs
IFN0YXR1cw0KKyAgICAgICk7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIE9yaWdpbmFs
VFBMID0gZ0JTLT5SYWlzZVRQTCAoVFBMX05PVElGWSk7DQorICBTdGF0dXMgPSBJbnRlbFZpcnR1
YWxHcHVCbHRWaWRlb0ZpbGwgKA0KKyAgICAgICAgICAgICBEaXNwbGF5LA0KKyAgICAgICAgICAg
ICAoRUZJX0dSQVBISUNTX09VVFBVVF9CTFRfUElYRUxfVU5JT04pe3swLCAwLCAwLCAwfX0sDQor
ICAgICAgICAgICAgIChCTFRfUkVDVEFOR0xFKXswLCAwLCBEaXNwbGF5LT5XaWR0aCwgRGlzcGxh
eS0+SGVpZ2h0fSk7DQorICBnQlMtPlJlc3RvcmVUUEwgKE9yaWdpbmFsVFBMKTsNCisgIGlmIChF
RklfRVJST1IgKFN0YXR1cykpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAg
ICAiRmFpbCB0byBjbGVhciByZWN0YW5nbGUgYXQgWyVkLCAlZF0gc2l6ZSAlZHglZCB3aXRoIGNv
bG9yIDB4JTA4eCwgc3RhdHVzICVkXG4iLA0KKyAgICAgIChCTFRfUkVDVEFOR0xFKXswLCAwLCBE
aXNwbGF5LT5XaWR0aCwgRGlzcGxheS0+SGVpZ2h0fS5YLA0KKyAgICAgIChCTFRfUkVDVEFOR0xF
KXswLCAwLCBEaXNwbGF5LT5XaWR0aCwgRGlzcGxheS0+SGVpZ2h0fS5ZLA0KKyAgICAgIChCTFRf
UkVDVEFOR0xFKXswLCAwLCBEaXNwbGF5LT5XaWR0aCwgRGlzcGxheS0+SGVpZ2h0fS5XaWR0aCwN
CisgICAgICAoQkxUX1JFQ1RBTkdMRSl7MCwgMCwgRGlzcGxheS0+V2lkdGgsIERpc3BsYXktPkhl
aWdodH0uSGVpZ2h0LA0KKyAgICAgIChFRklfR1JBUEhJQ1NfT1VUUFVUX0JMVF9QSVhFTF9VTklP
Til7ezAsIDAsIDAsIDB9fS5SYXcsDQorICAgICAgU3RhdHVzDQorICAgICAgKTsNCisgICAgZ290
byBEb25lOw0KKyAgfQ0KKw0KKyAgU3RhdHVzID0gZ0JTLT5BbGxvY2F0ZVBvb2wgKA0KKyAgICAg
ICAgICAgICAgICAgIEVmaUJvb3RTZXJ2aWNlc0RhdGEsDQorICAgICAgICAgICAgICAgICAgc2l6
ZW9mIChFRklfR1JBUEhJQ1NfT1VUUFVUX01PREVfSU5GT1JNQVRJT04pICogRGlzcGxheS0+TWF4
TW9kZSwNCisgICAgICAgICAgICAgICAgICAoVk9JRCAqKikmRGlzcGxheS0+TW9kZUxpc3QNCisg
ICAgICAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICBH
VlRfREVCVUcgKEVGSV9EX0VSUk9SLA0KKyAgICAgICJBbGxvY2F0ZVBvb2wgZmFpbGVkIGZvciBk
aXNwbGF5IG1vZGUgbGlzdCwgc2l6ZSAlZCwgc3RhdHVzICVkXG4iLA0KKyAgICAgIHNpemVvZiAo
RUZJX0dSQVBISUNTX09VVFBVVF9NT0RFX0lORk9STUFUSU9OKSAqIERpc3BsYXktPk1heE1vZGUs
DQorICAgICAgU3RhdHVzDQorICAgICAgKTsNCisgICAgU3RhdHVzID0gRUZJX09VVF9PRl9SRVNP
VVJDRVM7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIGZvciAoTW9kZU51bWJlciA9IDA7
IE1vZGVOdW1iZXIgPCBEaXNwbGF5LT5NYXhNb2RlOyBNb2RlTnVtYmVyKyspIHsNCisgICAgRGlz
cGxheS0+TW9kZUxpc3RbTW9kZU51bWJlcl0uVmVyc2lvbiA9IDA7DQorICAgIERpc3BsYXktPk1v
ZGVMaXN0W01vZGVOdW1iZXJdLkhvcml6b250YWxSZXNvbHV0aW9uID0gRGlzcGxheS0+V2lkdGg7
DQorICAgIERpc3BsYXktPk1vZGVMaXN0W01vZGVOdW1iZXJdLlZlcnRpY2FsUmVzb2x1dGlvbiA9
IERpc3BsYXktPkhlaWdodDsNCisgICAgRGlzcGxheS0+TW9kZUxpc3RbTW9kZU51bWJlcl0uUGl4
ZWxGb3JtYXQgPSBEaXNwbGF5LT5Gb3JtYXQ7DQorICAgIERpc3BsYXktPk1vZGVMaXN0W01vZGVO
dW1iZXJdLlBpeGVsc1BlclNjYW5MaW5lID0gRGlzcGxheS0+V2lkdGg7DQorICB9DQorICBpZiAo
RGlzcGxheS0+TWF4TW9kZSA+IDEpIHsNCisgICAgRGlzcGxheS0+TW9kZUxpc3RbMV0uSG9yaXpv
bnRhbFJlc29sdXRpb24gPSBQY2RHZXQzMiAoUGNkVmlkZW9Ib3Jpem9udGFsUmVzb2x1dGlvbik7
DQorICAgIERpc3BsYXktPk1vZGVMaXN0WzFdLlZlcnRpY2FsUmVzb2x1dGlvbiA9IFBjZEdldDMy
IChQY2RWaWRlb1ZlcnRpY2FsUmVzb2x1dGlvbik7DQorICAgIERpc3BsYXktPk1vZGVMaXN0WzFd
LlBpeGVsc1BlclNjYW5MaW5lID0gUGNkR2V0MzIgKFBjZFZpZGVvSG9yaXpvbnRhbFJlc29sdXRp
b24pOw0KKyAgfQ0KKw0KKyAgUHJpdmF0ZS0+R3JhcGhpY3NPdXRwdXRQcm90b2NvbC5RdWVyeU1v
ZGUgPSBJbnRlbFZpcnR1YWxHcHVRdWVyeU1vZGU7DQorICBQcml2YXRlLT5HcmFwaGljc091dHB1
dFByb3RvY29sLlNldE1vZGUgPSBJbnRlbFZpcnR1YWxHcHVTZXRNb2RlOw0KKyAgUHJpdmF0ZS0+
R3JhcGhpY3NPdXRwdXRQcm90b2NvbC5CbHQgPSBJbnRlbFZpcnR1YWxHcHVCbHQ7DQorICBQcml2
YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1vZGUtPk1heE1vZGUgPSBEaXNwbGF5LT5NYXhN
b2RlOw0KKyAgUHJpdmF0ZS0+R3JhcGhpY3NPdXRwdXRQcm90b2NvbC5Nb2RlLT5Nb2RlID0gRGlz
cGxheS0+Q3VycmVudE1vZGU7DQorICBQcml2YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1v
ZGUtPlNpemVPZkluZm8gPQ0KKyAgICBzaXplb2YoRUZJX0dSQVBISUNTX09VVFBVVF9NT0RFX0lO
Rk9STUFUSU9OKSAqIERpc3BsYXktPk1heE1vZGU7DQorDQorICBTdGF0dXMgPSBnQlMtPkFsbG9j
YXRlUG9vbCAoDQorICAgICAgICAgICAgICAgICAgRWZpQm9vdFNlcnZpY2VzRGF0YSwNCisgICAg
ICAgICAgICAgICAgICBQcml2YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1vZGUtPlNpemVP
ZkluZm8sDQorICAgICAgICAgICAgICAgICAgKFZPSUQgKiopJlByaXZhdGUtPkdyYXBoaWNzT3V0
cHV0UHJvdG9jb2wuTW9kZS0+SW5mbw0KKyAgICAgICAgICAgICAgICAgICk7DQorICBpZiAoRUZJ
X0VSUk9SIChTdGF0dXMpKSB7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAg
IkFsbG9jYXRlUG9vbCBmYWlsZWQgZm9yIGRpc3BsYXkgbW9kZSBpbmZvLCBzaXplICVkLCBzdGF0
dXMgJWRcbiIsDQorICAgICAgUHJpdmF0ZS0+R3JhcGhpY3NPdXRwdXRQcm90b2NvbC5Nb2RlLT5T
aXplT2ZJbmZvLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBTdGF0dXMgPSBFRklfT1VUX09GX1JF
U09VUkNFUzsNCisgICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyAgQ29weU1lbSAoDQorICAgIFBy
aXZhdGUtPkdyYXBoaWNzT3V0cHV0UHJvdG9jb2wuTW9kZS0+SW5mbywNCisgICAgRGlzcGxheS0+
TW9kZUxpc3QsDQorICAgIHNpemVvZiAoRUZJX0dSQVBISUNTX09VVFBVVF9NT0RFX0lORk9STUFU
SU9OKSAqIERpc3BsYXktPk1heE1vZGUNCisgICAgKTsNCisNCisgIFByaXZhdGUtPkdyYXBoaWNz
T3V0cHV0UHJvdG9jb2wuTW9kZS0+RnJhbWVCdWZmZXJCYXNlID0gRGlzcGxheS0+RmJHTUFkZHI7
DQorICBQcml2YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1vZGUtPkZyYW1lQnVmZmVyU2l6
ZSA9IERpc3BsYXktPkZiU2l6ZTsNCisNCisgIEluc3RhbGxWYmVTaGltIChMIkdWVC1nIFZCSU9T
IiwgRGlzcGxheS0+RmJHTUFkZHIpOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9JTkZPLA0KKyAg
ICAibW9kZXMgJWQsIG1heCAlZHglZCwgT1ZNRiBkZWZhdWx0ICVkeCVkXG4iLA0KKyAgICBEaXNw
bGF5LT5NYXhNb2RlLA0KKyAgICBEaXNwbGF5LT5XaWR0aCwgRGlzcGxheS0+SGVpZ2h0LA0KKyAg
ICBQY2RHZXQzMiAoUGNkVmlkZW9Ib3Jpem9udGFsUmVzb2x1dGlvbiksDQorICAgIFBjZEdldDMy
IChQY2RWaWRlb1ZlcnRpY2FsUmVzb2x1dGlvbikNCisgICAgKTsNCisgIGZvciAoTW9kZU51bWJl
ciA9IDA7IE1vZGVOdW1iZXIgPCBEaXNwbGF5LT5NYXhNb2RlOyBNb2RlTnVtYmVyKyspIHsNCisg
ICAgR1ZUX0RFQlVHIChFRklfRF9JTkZPLA0KKyAgICAgICIgIG1vZGUgJWQ6ICVkeCVkIEJHUlgs
IHN0cmlkZSAlZFxuIiwNCisgICAgICBNb2RlTnVtYmVyLA0KKyAgICAgIERpc3BsYXktPk1vZGVM
aXN0W01vZGVOdW1iZXJdLkhvcml6b250YWxSZXNvbHV0aW9uLA0KKyAgICAgIERpc3BsYXktPk1v
ZGVMaXN0W01vZGVOdW1iZXJdLlZlcnRpY2FsUmVzb2x1dGlvbiwNCisgICAgICBBTElHTl9WQUxV
RSAoRGlzcGxheS0+TW9kZUxpc3RbTW9kZU51bWJlcl0uSG9yaXpvbnRhbFJlc29sdXRpb24gKiBE
aXNwbGF5LT5CcHAsIDY0KQ0KKyAgICAgICk7DQorICB9DQorICBHVlRfREVCVUcgKEVGSV9EX0lO
Rk8sDQorICAgICJGcmFtZUJ1ZmZlcjogR01BRFIgJWx4LCBQQUREUiAlbHgsIHNpemUgJWx4LCBw
YWdlcyAlZCwgSU5URVJOQUxfQkxUICVkXG4iLA0KKyAgICBEaXNwbGF5LT5GYkdNQWRkciwgRGlz
cGxheS0+RmJQaHlzaWNhbEFkZHIsIERpc3BsYXktPkZiU2l6ZSwgRGlzcGxheS0+UGFnZXMsDQor
ICAgIERJU1BMQVlfVVNFX0lOVEVSTkFMX0JMVA0KKyAgICApOw0KKw0KK0RvbmU6DQorDQorICBH
VlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsICIlYTogPDw8XG4iLCBfX0ZVTkNUSU9OX18pOw0KKw0K
KyAgcmV0dXJuIFN0YXR1czsNCisNCit9DQorDQorRUZJX1NUQVRVUw0KK0ludGVsVmlydHVhbEdw
dURpc3BsYXlDbGVhbiAoDQorICBJTiBPVVQgR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlByaXZhdGUN
CisgICkNCit7DQorICBFRklfU1RBVFVTICAgICAgICAgICAgICAgICBTdGF0dXMgPSBFRklfSU5W
QUxJRF9QQVJBTUVURVI7DQorICBQSU5URUxfVklSVFVBTF9HUFUgICAgICAgICBWaXJ0dWFsR3B1
Ow0KKyAgUElOVEVMX1ZJUlRVQUxfR1BVX0RJU1BMQVkgRGlzcGxheTsNCisNCisgIEdWVF9ERUJV
RyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA+Pj5cbiIsIF9fRlVOQ1RJT05fXyk7DQorDQorICBWaXJ0
dWFsR3B1ID0gKFBJTlRFTF9WSVJUVUFMX0dQVSlQcml2YXRlLT5WaXJ0dWFsR3B1Ow0KKyAgRGlz
cGxheSA9ICZWaXJ0dWFsR3B1LT5EaXNwbGF5Ow0KKw0KKyAgaWYgKFByaXZhdGUtPkdyYXBoaWNz
T3V0cHV0UHJvdG9jb2wuTW9kZS0+SW5mbykgew0KKyAgICBTdGF0dXMgPSBnQlMtPkZyZWVQb29s
IChQcml2YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1vZGUtPkluZm8pOw0KKyAgICBpZiAo
RUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisg
ICAgICAgICJGcmVlUG9vbCBmYWlsZWQgZm9yIGRpc3BsYXkgbW9kZSBpbmZvLCBzaXplICVkLCBz
dGF0dXMgJWRcbiIsDQorICAgICAgICBQcml2YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1v
ZGUtPlNpemVPZkluZm8sIFN0YXR1cw0KKyAgICAgICAgKTsNCisgICAgICAgIGdvdG8gRG9uZTsN
CisgICAgfQ0KKyAgICBQcml2YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1vZGUtPlNpemVP
ZkluZm8gPSAwOw0KKyAgICBQcml2YXRlLT5HcmFwaGljc091dHB1dFByb3RvY29sLk1vZGUtPklu
Zm8gPSBOVUxMOw0KKyAgfQ0KKyAgUHJpdmF0ZS0+R3JhcGhpY3NPdXRwdXRQcm90b2NvbC5Nb2Rl
LT5NYXhNb2RlID0gMDsNCisgIFByaXZhdGUtPkdyYXBoaWNzT3V0cHV0UHJvdG9jb2wuTW9kZS0+
TW9kZSA9IERJU1BMQVlfTU9ERV9JTlZBTElEOw0KKw0KKyAgaWYgKERpc3BsYXktPkZiUGh5c2lj
YWxBZGRyKSB7DQorICAgIFN0YXR1cyA9IGdCUy0+RnJlZVBhZ2VzIChEaXNwbGF5LT5GYlBoeXNp
Y2FsQWRkciwgRGlzcGxheS0+UGFnZXMpOw0KKyAgICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7
DQorICAgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAgICJGcmVlUGFnZXMgZmFp
bGVkIGZvciBkaXNwbGF5IEZCLCBwYWdlcyAlZCwgc2l6ZSAlbHgsIHN0YXR1cyAlZFxuIiwNCisg
ICAgICAgIERpc3BsYXktPlBhZ2VzLCBEaXNwbGF5LT5GYlNpemUsIFN0YXR1cw0KKyAgICAgICAg
KTsNCisgICAgICAgIGdvdG8gRG9uZTsNCisgICAgfQ0KKyAgICBEaXNwbGF5LT5GYlBoeXNpY2Fs
QWRkciA9IDA7DQorICAgIERpc3BsYXktPlBhZ2VzID0gMDsNCisgICAgRGlzcGxheS0+RmJTaXpl
ID0gMDsNCisgIH0NCisNCisgIFN0YXR1cyA9IEVGSV9TVUNDRVNTOw0KKw0KK0RvbmU6DQorDQor
ICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsICIlYTogPDw8XG4iLCBfX0ZVTkNUSU9OX18pOw0K
Kw0KKyAgcmV0dXJuIFN0YXR1czsNCit9DQorDQorRUZJX1NUQVRVUw0KK0VGSUFQSQ0KK0ludGVs
VmlydHVhbEdwdVF1ZXJ5TW9kZSAoDQorICBJTiAgRUZJX0dSQVBISUNTX09VVFBVVF9QUk9UT0NP
TCAgICAgICAgICpUaGlzLA0KKyAgSU4gIFVJTlQzMiAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICBNb2RlTnVtYmVyLA0KKyAgT1VUIFVJTlROICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAqU2l6ZU9mSW5mbywNCisgIE9VVCBFRklfR1JBUEhJQ1NfT1VUUFVUX01PREVfSU5GT1JN
QVRJT04gKipJbmZvDQorICApDQorew0KKyAgRUZJX1NUQVRVUyAgICAgICAgICAgICAgICAgU3Rh
dHVzID0gRUZJX1VOU1VQUE9SVEVEOw0KKyAgR1ZUX0dPUF9QUklWQVRFX0RBVEEgICAgICAgKkd2
dEdvcFByaXZhdGUgPSBOVUxMOw0KKyAgUElOVEVMX1ZJUlRVQUxfR1BVICAgICAgICAgVmlydHVh
bEdwdTsNCisgIFBJTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZIERpc3BsYXk7DQorDQorICBHVlRf
REVCVUcgKEVGSV9EX1ZFUkJPU0UsICIlYTogPj4+XG4iLCBfX0ZVTkNUSU9OX18pOw0KKw0KKyAg
R3Z0R29wUHJpdmF0ZSA9IEdWVF9HT1BfUFJJVkFURV9EQVRBX0ZST01fVEhJUyAoVGhpcyk7DQor
ICBWaXJ0dWFsR3B1ID0gKFBJTlRFTF9WSVJUVUFMX0dQVSlHdnRHb3BQcml2YXRlLT5WaXJ0dWFs
R3B1Ow0KKyAgRGlzcGxheSA9ICZWaXJ0dWFsR3B1LT5EaXNwbGF5Ow0KKw0KKyAgaWYgKE1vZGVO
dW1iZXIgPj0gRGlzcGxheS0+TWF4TW9kZSkgew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9S
LA0KKyAgICAgICJJbnZhbGlkIE1vZGVOdW1iZXIsIHJlcXVlc3QgJWQsIG1heCAlZCwgc3RhdHVz
ICVkXG4iLA0KKyAgICAgIE1vZGVOdW1iZXIsIERpc3BsYXktPk1heE1vZGUsIFN0YXR1cw0KKyAg
ICAgICk7DQorICAgIFN0YXR1cyA9IEVGSV9JTlZBTElEX1BBUkFNRVRFUjsNCisgICAgZ290byBE
b25lOw0KKyAgfQ0KKw0KKyAgU3RhdHVzID0gZ0JTLT5BbGxvY2F0ZVBvb2wgKA0KKyAgICAgICAg
ICAgICAgICAgIEVmaUJvb3RTZXJ2aWNlc0RhdGEsDQorICAgICAgICAgICAgICAgICAgc2l6ZW9m
KEVGSV9HUkFQSElDU19PVVRQVVRfTU9ERV9JTkZPUk1BVElPTiksDQorICAgICAgICAgICAgICAg
ICAgKFZPSUQgKiopSW5mbw0KKyAgICAgICAgICAgICAgICAgICk7DQorICBpZiAoRUZJX0VSUk9S
IChTdGF0dXMpIHx8ICpJbmZvID09IE5VTEwpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJP
UiwNCisgICAgICAiQWxsb2NhdGVQb29sIGZhaWxlZCBmb3IgcXVlcmllZCBtb2RlIGluZm8sIHNp
emUgJWQsIHN0YXR1cyAlZFxuIiwNCisgICAgICBzaXplb2YoRUZJX0dSQVBISUNTX09VVFBVVF9N
T0RFX0lORk9STUFUSU9OKSwgU3RhdHVzDQorICAgICAgKTsNCisgICAgU3RhdHVzID0gRUZJX09V
VF9PRl9SRVNPVVJDRVM7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgICpTaXplT2ZJbmZv
ID0gc2l6ZW9mIChFRklfR1JBUEhJQ1NfT1VUUFVUX01PREVfSU5GT1JNQVRJT04pOw0KKyAgQ29w
eU1lbSAoDQorICAgICpJbmZvLA0KKyAgICAmRGlzcGxheS0+TW9kZUxpc3RbTW9kZU51bWJlcl0s
DQorICAgIHNpemVvZiAoRUZJX0dSQVBISUNTX09VVFBVVF9NT0RFX0lORk9STUFUSU9OKQ0KKyAg
ICApOw0KKw0KKyAgU3RhdHVzID0gRUZJX1NVQ0NFU1M7DQorDQorRG9uZToNCisNCisgIEdWVF9E
RUJVRyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA8PDxcbiIsIF9fRlVOQ1RJT05fXyk7DQorDQorICBy
ZXR1cm4gU3RhdHVzOw0KK30NCisNCitFRklfU1RBVFVTDQorRUZJQVBJDQorSW50ZWxWaXJ0dWFs
R3B1U2V0TW9kZSAoDQorICBJTiBFRklfR1JBUEhJQ1NfT1VUUFVUX1BST1RPQ09MICpUaGlzLA0K
KyAgSU4gVUlOVDMyICAgICAgICAgICAgICAgICAgICAgICBNb2RlTnVtYmVyDQorICApDQorew0K
KyAgRUZJX1NUQVRVUyAgICAgICAgICAgICAgICAgICAgICAgICAgU3RhdHVzID0gRUZJX1VOU1VQ
UE9SVEVEOw0KKyAgR1ZUX0dPUF9QUklWQVRFX0RBVEEgICAgICAgICAgICAgICAgKkd2dEdvcFBy
aXZhdGUgPSBOVUxMOw0KKyAgUElOVEVMX1ZJUlRVQUxfR1BVICAgICAgICAgICAgICAgICAgVmly
dHVhbEdwdTsNCisgIFBJTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZICAgICAgICAgIERpc3BsYXk7
DQorDQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsICIlYTogPj4+XG4iLCBfX0ZVTkNUSU9O
X18pOw0KKw0KKyAgR3Z0R29wUHJpdmF0ZSA9IEdWVF9HT1BfUFJJVkFURV9EQVRBX0ZST01fVEhJ
UyAoVGhpcyk7DQorICBWaXJ0dWFsR3B1ID0gKFBJTlRFTF9WSVJUVUFMX0dQVSlHdnRHb3BQcml2
YXRlLT5WaXJ0dWFsR3B1Ow0KKyAgRGlzcGxheSA9ICZWaXJ0dWFsR3B1LT5EaXNwbGF5Ow0KKw0K
KyAgaWYgKE1vZGVOdW1iZXIgPj0gRGlzcGxheS0+TWF4TW9kZSkgew0KKyAgICBHVlRfREVCVUcg
KEVGSV9EX0VSUk9SLA0KKyAgICAgICJJbnZhbGlkIE1vZGVOdW1iZXIsIHJlcXVlc3QgJWQsIG1h
eCAlZCwgc3RhdHVzICVkXG4iLA0KKyAgICAgIE1vZGVOdW1iZXIsIERpc3BsYXktPk1heE1vZGUs
IFN0YXR1cw0KKyAgICAgICk7DQorICAgIFN0YXR1cyA9IEVGSV9JTlZBTElEX1BBUkFNRVRFUjsN
CisgICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyNpZiAoRElTUExBWV9VU0VfSU5URVJOQUxfQkxU
ID09IDEpDQorICBTdGF0dXMgPSBJbnRlbFZpcnR1YWxHcHVCbHRWaWRlb0ZpbGwgKA0KKyAgICAg
ICAgICAgICBEaXNwbGF5LA0KKyAgICAgICAgICAgICAoRUZJX0dSQVBISUNTX09VVFBVVF9CTFRf
UElYRUxfVU5JT04pe3swLCAwLCAwLCAwfX0sDQorICAgICAgICAgICAgIChCTFRfUkVDVEFOR0xF
KXswLCAwLCBUaGlzLT5Nb2RlLT5JbmZvLT5Ib3Jpem9udGFsUmVzb2x1dGlvbiwgVGhpcy0+TW9k
ZS0+SW5mby0+VmVydGljYWxSZXNvbHV0aW9ufSk7DQorICBpZiAoRUZJX0VSUk9SIChTdGF0dXMp
KSB7DQorICAgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAgICJJbnRlbFZpcnR1
YWxHcHVCbHRWaWRlb0ZpbGwgZmFpbGVkIGZvciBtb2RlICVkLCBzdGF0dXMgJWRcbiIsDQorICAg
ICAgICBNb2RlTnVtYmVyLA0KKyAgICAgICAgU3RhdHVzDQorICAgICAgICApOw0KKyAgICB9DQor
I2Vsc2UNCisgIFN0YXR1cyA9IEZyYW1lQnVmZmVyQmx0Q29uZmlndXJlICgNCisgICAgICAgICAg
ICAgKFZPSUQqKSAoVUlOVE4pIFRoaXMtPk1vZGUtPkZyYW1lQnVmZmVyQmFzZSwNCisgICAgICAg
ICAgICAgVGhpcy0+TW9kZS0+SW5mbywNCisgICAgICAgICAgICAgRGlzcGxheS0+RnJhbWVCdWZm
ZXJCbHRDb25maWd1cmUsDQorICAgICAgICAgICAgICZEaXNwbGF5LT5GcmFtZUJ1ZmZlckJsdENv
bmZpZ3VyZVNpemUNCisgICAgICAgICAgICAgKTsNCisgIGlmIChTdGF0dXMgPT0gUkVUVVJOX0JV
RkZFUl9UT09fU01BTEwpIHsNCisgICAgaWYgKERpc3BsYXktPkZyYW1lQnVmZmVyQmx0Q29uZmln
dXJlICE9IE5VTEwpIHsNCisgICAgICBTdGF0dXMgPSBnQlMtPkZyZWVQb29sIChEaXNwbGF5LT5G
cmFtZUJ1ZmZlckJsdENvbmZpZ3VyZSk7DQorICAgICAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkg
ew0KKyAgICAgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAgICAgIkZyZWVQb29s
IGZhaWxlZCBmb3IgRnJhbWVCdWZmZXJCbHRDb25maWd1cmUsIHN0YXR1cyAlZFxuIiwNCisgICAg
ICAgICAgU3RhdHVzDQorICAgICAgICAgICk7DQorICAgICAgICAgIGdvdG8gRG9uZTsNCisgICAg
ICB9DQorICAgIH0NCisgICAgU3RhdHVzID0gZ0JTLT5BbGxvY2F0ZVBvb2wgKA0KKyAgICAgICAg
ICAgICAgICAgIEVmaUJvb3RTZXJ2aWNlc0RhdGEsDQorICAgICAgICAgICAgICAgICAgRGlzcGxh
eS0+RnJhbWVCdWZmZXJCbHRDb25maWd1cmVTaXplLA0KKyAgICAgICAgICAgICAgICAgIChWT0lE
ICoqKSZEaXNwbGF5LT5GcmFtZUJ1ZmZlckJsdENvbmZpZ3VyZQ0KKyAgICAgICAgICAgICAgICAg
ICk7DQorICAgIGlmIChFRklfRVJST1IgKFN0YXR1cykpIHsNCisgICAgICBHVlRfREVCVUcgKEVG
SV9EX0VSUk9SLA0KKyAgICAgICAgIkFsbG9jYXRlUG9vbCBmYWlsZWQgZm9yIEZyYW1lQnVmZmVy
Qmx0Q29uZmlndXJlLCBzaXplICVkLCBzdGF0dXMgJWRcbiIsDQorICAgICAgICBEaXNwbGF5LT5G
cmFtZUJ1ZmZlckJsdENvbmZpZ3VyZVNpemUsDQorICAgICAgICBTdGF0dXMNCisgICAgICAgICk7
DQorICAgICAgZ290byBEb25lOw0KKyAgICB9DQorDQorICAgIFN0YXR1cyA9IEZyYW1lQnVmZmVy
Qmx0Q29uZmlndXJlICgNCisgICAgICAgICAgICAgICAgKFZPSUQqKSAoVUlOVE4pIFRoaXMtPk1v
ZGUtPkZyYW1lQnVmZmVyQmFzZSwNCisgICAgICAgICAgICAgICAgVGhpcy0+TW9kZS0+SW5mbywN
CisgICAgICAgICAgICAgICAgRGlzcGxheS0+RnJhbWVCdWZmZXJCbHRDb25maWd1cmUsDQorICAg
ICAgICAgICAgICAgICZEaXNwbGF5LT5GcmFtZUJ1ZmZlckJsdENvbmZpZ3VyZVNpemUNCisgICAg
ICAgICAgICAgICAgKTsNCisgICAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICAgIEdW
VF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgICAiRnJhbWVCdWZmZXJCbHRDb25maWd1cmUg
ZmFpbGVkIGZvciBtb2RlICVkLCBzdGF0dXMgJWRcbiIsDQorICAgICAgICBNb2RlTnVtYmVyLA0K
KyAgICAgICAgU3RhdHVzDQorICAgICAgICApOw0KKyAgICAgIGdvdG8gRG9uZTsNCisgICAgfQ0K
KyAgfQ0KKw0KKyAgU3RhdHVzID0gRnJhbWVCdWZmZXJCbHQgKA0KKyAgICAgICAgICAgICBEaXNw
bGF5LT5GcmFtZUJ1ZmZlckJsdENvbmZpZ3VyZSwNCisgICAgICAgICAgICAgJihFRklfR1JBUEhJ
Q1NfT1VUUFVUX0JMVF9QSVhFTCl7MCwgMCwgMCwgMH0sDQorICAgICAgICAgICAgIEVmaUJsdFZp
ZGVvRmlsbCwNCisgICAgICAgICAgICAgMCwgMCwNCisgICAgICAgICAgICAgMCwgMCwNCisgICAg
ICAgICAgICAgVGhpcy0+TW9kZS0+SW5mby0+SG9yaXpvbnRhbFJlc29sdXRpb24sDQorICAgICAg
ICAgICAgIFRoaXMtPk1vZGUtPkluZm8tPlZlcnRpY2FsUmVzb2x1dGlvbiwNCisgICAgICAgICAg
ICAgMA0KKyAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAg
ICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgICAiRnJhbWVCdWZmZXJCbHQgQmx0
T3BlcmF0aW9uICVkIGZhaWxlZCBmb3IgbW9kZSAlZCwgY29sb3IgMHglMDh4LCBzdGF0dXMgJWRc
biIsDQorICAgICAgICBFZmlCbHRWaWRlb0ZpbGwsDQorICAgICAgICBNb2RlTnVtYmVyLA0KKyAg
ICAgICAgKEVGSV9HUkFQSElDU19PVVRQVVRfQkxUX1BJWEVMX1VOSU9OKXt7MCwgMCwgMCwgMH19
LlJhdywNCisgICAgICAgIFN0YXR1cw0KKyAgICAgICAgKTsNCisgICAgfQ0KKyNlbmRpZg0KKw0K
KyAgU3RhdHVzID0gSW50ZWxWaXJ0dWFsR3B1RW5hYmxlRGlzcGxheSAoDQorICAgICAgICAgICAg
IEd2dEdvcFByaXZhdGUsDQorICAgICAgICAgICAgIE1vZGVOdW1iZXIsDQorICAgICAgICAgICAg
IEZBTFNFDQorICAgICAgICAgICAgICk7DQorDQorICBTdGF0dXMgPSBJbnRlbFZpcnR1YWxHcHVF
bmFibGVEaXNwbGF5ICgNCisgICAgICAgICAgICAgR3Z0R29wUHJpdmF0ZSwNCisgICAgICAgICAg
ICAgTW9kZU51bWJlciwNCisgICAgICAgICAgICAgVFJVRQ0KKyAgICAgICAgICAgICApOw0KKw0K
KyAgLy8gU2V0IGN1cnJlbnQgbW9kZSBpbmZvIGluIEdPUA0KKyAgVGhpcy0+TW9kZS0+TW9kZSA9
IE1vZGVOdW1iZXI7DQorICBDb3B5TWVtICgNCisgICAgVGhpcy0+TW9kZS0+SW5mbywNCisgICAg
JkRpc3BsYXktPk1vZGVMaXN0W01vZGVOdW1iZXJdLA0KKyAgICBzaXplb2YgKEVGSV9HUkFQSElD
U19PVVRQVVRfTU9ERV9JTkZPUk1BVElPTikNCisgICAgKTsNCisNCisgIEdWVF9ERUJVRyAoRUZJ
X0RfSU5GTywgIlNldCBtb2RlICVkLCAlZHglZCwgc3RhdHVzICVkXG4iLA0KKyAgICBNb2RlTnVt
YmVyLA0KKyAgICBEaXNwbGF5LT5Nb2RlTGlzdFtNb2RlTnVtYmVyXS5Ib3Jpem9udGFsUmVzb2x1
dGlvbiwNCisgICAgRGlzcGxheS0+TW9kZUxpc3RbTW9kZU51bWJlcl0uVmVydGljYWxSZXNvbHV0
aW9uLA0KKyAgICBTdGF0dXMNCisgICAgKTsNCisNCitEb25lOg0KKyAgR1ZUX0RFQlVHIChFRklf
RF9WRVJCT1NFLCAiJWE6IDw8PFxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIHJldHVybiBTdGF0
dXM7DQorfQ0KKw0KK0VGSV9TVEFUVVMNCitFRklBUEkNCitJbnRlbFZpcnR1YWxHcHVCbHQgKA0K
KyAgSU4gRUZJX0dSQVBISUNTX09VVFBVVF9QUk9UT0NPTCAgICAgICpUaGlzLA0KKyAgSU4gRUZJ
X0dSQVBISUNTX09VVFBVVF9CTFRfUElYRUwgICAgICpCbHRCdWZmZXIsIE9QVElPTkFMDQorICBJ
TiBFRklfR1JBUEhJQ1NfT1VUUFVUX0JMVF9PUEVSQVRJT04gQmx0T3BlcmF0aW9uLA0KKyAgSU4g
VUlOVE4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNvdXJjZVgsDQorICBJTiBVSU5UTiAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgU291cmNlWSwNCisgIElOIFVJTlROICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBEZXN0aW5hdGlvblgsDQorICBJTiBVSU5UTiAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgRGVzdGluYXRpb25ZLA0KKyAgSU4gVUlOVE4gICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIFdpZHRoLA0KKyAgSU4gVUlOVE4gICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIEhlaWdodCwNCisgIElOIFVJTlROICAgICAgICAgICAgICAgICAgICAgICAgICAgICBE
ZWx0YSBPUFRJT05BTA0KKyAgKQ0KK3sNCisgIEVGSV9TVEFUVVMgICAgICAgICAgICAgICAgIFN0
YXR1cyA9IEVGSV9VTlNVUFBPUlRFRDsNCisgIEdWVF9HT1BfUFJJVkFURV9EQVRBICAgICAgICpH
dnRHb3BQcml2YXRlID0gTlVMTDsNCisgIFBJTlRFTF9WSVJUVUFMX0dQVSAgICAgICAgIFZpcnR1
YWxHcHU7DQorICBQSU5URUxfVklSVFVBTF9HUFVfRElTUExBWSBEaXNwbGF5Ow0KKyAgRUZJX1RQ
TCAgICAgICAgICAgICAgICAgICAgT3JpZ2luYWxUUEw7DQorDQorICBHVlRfREVCVUcgKEVGSV9E
X1ZFUkJPU0UsICIlYTogPj4+XG4iLCBfX0ZVTkNUSU9OX18pOw0KKw0KKyAgR3Z0R29wUHJpdmF0
ZSA9IEdWVF9HT1BfUFJJVkFURV9EQVRBX0ZST01fVEhJUyAoVGhpcyk7DQorICBWaXJ0dWFsR3B1
ID0gKFBJTlRFTF9WSVJUVUFMX0dQVSlHdnRHb3BQcml2YXRlLT5WaXJ0dWFsR3B1Ow0KKyAgRGlz
cGxheSA9ICZWaXJ0dWFsR3B1LT5EaXNwbGF5Ow0KKw0KKyAgT3JpZ2luYWxUUEwgPSBnQlMtPlJh
aXNlVFBMIChUUExfTk9USUZZKTsNCisNCisjaWYgKERJU1BMQVlfVVNFX0lOVEVSTkFMX0JMVCA9
PSAxKQ0KKyAgc3dpdGNoIChCbHRPcGVyYXRpb24pIHsNCisgIGNhc2UgRWZpQmx0VmlkZW9GaWxs
Og0KKyAgICBTdGF0dXMgPSBJbnRlbFZpcnR1YWxHcHVCbHRWaWRlb0ZpbGwgKA0KKyAgICAgICAg
ICAgICAgIERpc3BsYXksDQorICAgICAgICAgICAgICAgKEVGSV9HUkFQSElDU19PVVRQVVRfQkxU
X1BJWEVMX1VOSU9OKSgqQmx0QnVmZmVyKSwNCisgICAgICAgICAgICAgICAoQkxUX1JFQ1RBTkdM
RSl7RGVzdGluYXRpb25YLCBEZXN0aW5hdGlvblksIFdpZHRoLCBIZWlnaHR9KTsNCisgICAgUmVn
V3JpdGUzMiAoR3Z0R29wUHJpdmF0ZSwNCisgICAgICBQTEFORV9TVVJGKFBJUEVfQSwgUExBTkVf
UFJJTUFSWSksDQorICAgICAgRGlzcGxheS0+RmJHTUFkZHINCisgICAgICApOw0KKyAgICBicmVh
azsNCisgIGNhc2UgRWZpQmx0VmlkZW9Ub0JsdEJ1ZmZlcjoNCisgICAgU3RhdHVzID0gSW50ZWxW
aXJ0dWFsR3B1Qmx0VmlkZW9Ub0J1ZmZlciAoDQorICAgICAgICAgICAgICAgRGlzcGxheSwNCisg
ICAgICAgICAgICAgICBCbHRCdWZmZXIsDQorICAgICAgICAgICAgICAgKEJMVF9SRUNUQU5HTEUp
e1NvdXJjZVgsIFNvdXJjZVksIFdpZHRoLCBIZWlnaHR9LA0KKyAgICAgICAgICAgICAgIChCTFRf
UkVDVEFOR0xFKXtEZXN0aW5hdGlvblgsIERlc3RpbmF0aW9uWSwgV2lkdGgsIEhlaWdodH0sDQor
ICAgICAgICAgICAgICAgRGVsdGENCisgICAgICAgICAgICAgICApOw0KKyAgICBicmVhazsNCisg
IGNhc2UgRWZpQmx0QnVmZmVyVG9WaWRlbzoNCisgICAgU3RhdHVzID0gSW50ZWxWaXJ0dWFsR3B1
Qmx0VmlkZW9Gcm9tQnVmZmVyICgNCisgICAgICAgICAgICAgICBEaXNwbGF5LA0KKyAgICAgICAg
ICAgICAgIEJsdEJ1ZmZlciwNCisgICAgICAgICAgICAgICAoQkxUX1JFQ1RBTkdMRSl7U291cmNl
WCwgU291cmNlWSwgV2lkdGgsIEhlaWdodH0sDQorICAgICAgICAgICAgICAgKEJMVF9SRUNUQU5H
TEUpe0Rlc3RpbmF0aW9uWCwgRGVzdGluYXRpb25ZLCBXaWR0aCwgSGVpZ2h0fSwNCisgICAgICAg
ICAgICAgICBEZWx0YQ0KKyAgICAgICAgICAgICAgICk7DQorICAgIFJlZ1dyaXRlMzIgKEd2dEdv
cFByaXZhdGUsDQorICAgICAgUExBTkVfU1VSRihQSVBFX0EsIFBMQU5FX1BSSU1BUlkpLA0KKyAg
ICAgIERpc3BsYXktPkZiR01BZGRyDQorICAgICAgKTsNCisgICAgYnJlYWs7DQorICBjYXNlIEVm
aUJsdFZpZGVvVG9WaWRlbzoNCisgICAgU3RhdHVzID0gSW50ZWxWaXJ0dWFsR3B1Qmx0VmlkZW9U
b1ZpZGVvICgNCisgICAgICAgICAgICAgICBEaXNwbGF5LA0KKyAgICAgICAgICAgICAgIChCTFRf
UkVDVEFOR0xFKXtTb3VyY2VYLCBTb3VyY2VZLCBXaWR0aCwgSGVpZ2h0fSwNCisgICAgICAgICAg
ICAgICAoQkxUX1JFQ1RBTkdMRSl7RGVzdGluYXRpb25YLCBEZXN0aW5hdGlvblksIFdpZHRoLCBI
ZWlnaHR9DQorICAgICAgICAgICAgICAgKTsNCisgICAgUmVnV3JpdGUzMiAoR3Z0R29wUHJpdmF0
ZSwNCisgICAgICBQTEFORV9TVVJGKFBJUEVfQSwgUExBTkVfUFJJTUFSWSksDQorICAgICAgRGlz
cGxheS0+RmJHTUFkZHINCisgICAgICApOw0KKyAgICBicmVhazsNCisgIGRlZmF1bHQ6DQorICAg
IEdWVF9ERUJVRyAoRUZJX0RfSU5GTywgIlVuc3VwcG9ydGVkIEVGSV9HUkFQSElDU19PVVRQVVRf
QkxUX09QRVJBVElPTiAlZFxuIiwgQmx0T3BlcmF0aW9uKTsNCisgICAgU3RhdHVzID0gRUZJX1VO
U1VQUE9SVEVEOw0KKyAgICBicmVhazsNCisgIH0NCisjZWxzZQ0KKyAgc3dpdGNoIChCbHRPcGVy
YXRpb24pIHsNCisgIGNhc2UgRWZpQmx0VmlkZW9Ub0JsdEJ1ZmZlcjoNCisgIGNhc2UgRWZpQmx0
VmlkZW9GaWxsOg0KKyAgY2FzZSBFZmlCbHRCdWZmZXJUb1ZpZGVvOg0KKyAgY2FzZSBFZmlCbHRW
aWRlb1RvVmlkZW86DQorICAgIFN0YXR1cyA9IEZyYW1lQnVmZmVyQmx0ICgNCisgICAgICAgICAg
ICAgICBEaXNwbGF5LT5GcmFtZUJ1ZmZlckJsdENvbmZpZ3VyZSwNCisgICAgICAgICAgICAgICBC
bHRCdWZmZXIsDQorICAgICAgICAgICAgICAgQmx0T3BlcmF0aW9uLA0KKyAgICAgICAgICAgICAg
IFNvdXJjZVgsDQorICAgICAgICAgICAgICAgU291cmNlWSwNCisgICAgICAgICAgICAgICBEZXN0
aW5hdGlvblgsDQorICAgICAgICAgICAgICAgRGVzdGluYXRpb25ZLA0KKyAgICAgICAgICAgICAg
IFdpZHRoLA0KKyAgICAgICAgICAgICAgIEhlaWdodCwNCisgICAgICAgICAgICAgICBEZWx0YQ0K
KyAgICAgICAgICAgICAgICk7DQorICAgIGlmIChCbHRPcGVyYXRpb24gIT0gRWZpQmx0VmlkZW9U
b0JsdEJ1ZmZlcikgew0KKyAgICAgIFJlZ1dyaXRlMzIgKEd2dEdvcFByaXZhdGUsDQorICAgICAg
ICBQTEFORV9TVVJGKFBJUEVfQSwgUExBTkVfUFJJTUFSWSksDQorICAgICAgICBEaXNwbGF5LT5G
YkdNQWRkcg0KKyAgICAgICAgKTsNCisgICAgfQ0KKyAgICBicmVhazsNCisgIGRlZmF1bHQ6DQor
ICAgIEdWVF9ERUJVRyAoRUZJX0RfSU5GTywgIlVuc3VwcG9ydGVkIEVGSV9HUkFQSElDU19PVVRQ
VVRfQkxUX09QRVJBVElPTiAlZFxuIiwgQmx0T3BlcmF0aW9uKTsNCisgICAgU3RhdHVzID0gRUZJ
X1VOU1VQUE9SVEVEOw0KKyAgICBicmVhazsNCisgIH0NCisjZW5kaWYNCisNCisgIGdCUy0+UmVz
dG9yZVRQTCAoT3JpZ2luYWxUUEwpOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAi
JWE6IDw8PFxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIHJldHVybiBTdGF0dXM7DQorfQ0KKw0K
K0VGSV9TVEFUVVMNCitJbnRlbFZpcnR1YWxHcHVFbmFibGVEaXNwbGF5ICgNCisgIElOIE9VVCBH
VlRfR09QX1BSSVZBVEVfREFUQSAqUHJpdmF0ZSwNCisgIElOICAgICBVSU5UMzIgICAgICAgICAg
ICAgICBNb2RlTnVtYmVyLA0KKyAgSU4gICAgIEJPT0xFQU4gICAgICAgICAgICAgIEVuYWJsZQ0K
KyAgKQ0KK3sNCisgIEVGSV9TVEFUVVMgICAgICAgICAgICAgICAgIFN0YXR1cyA9IEVGSV9JTlZB
TElEX1BBUkFNRVRFUjsNCisgIFBJTlRFTF9WSVJUVUFMX0dQVSAgICAgICAgIFZpcnR1YWxHcHU7
DQorICBQSU5URUxfVklSVFVBTF9HUFVfRElTUExBWSBEaXNwbGF5Ow0KKyAgVUlOVDMyICAgICAg
ICAgICAgICAgICAgICAgV2lkdGgsIEhlaWdodCwgVmFsMzI7DQorDQorICBHVlRfREVCVUcgKEVG
SV9EX1ZFUkJPU0UsICIlYTogPj4+XG4iLCBfX0ZVTkNUSU9OX18pOw0KKw0KKyAgVmlydHVhbEdw
dSA9IChQSU5URUxfVklSVFVBTF9HUFUpUHJpdmF0ZS0+VmlydHVhbEdwdTsNCisgIERpc3BsYXkg
PSAmVmlydHVhbEdwdS0+RGlzcGxheTsNCisNCisgIGlmIChNb2RlTnVtYmVyID49IERpc3BsYXkt
Pk1heE1vZGUpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiSW52YWxp
ZCBNb2RlTnVtYmVyLCByZXF1ZXN0ICVkLCBtYXggJWQsIHN0YXR1cyAlZFxuIiwNCisgICAgICBN
b2RlTnVtYmVyLCBEaXNwbGF5LT5NYXhNb2RlLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBTdGF0
dXMgPSBFRklfSU5WQUxJRF9QQVJBTUVURVI7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisg
IFdpZHRoID0gRGlzcGxheS0+TW9kZUxpc3RbTW9kZU51bWJlcl0uSG9yaXpvbnRhbFJlc29sdXRp
b247DQorICBIZWlnaHQgPSBEaXNwbGF5LT5Nb2RlTGlzdFtNb2RlTnVtYmVyXS5WZXJ0aWNhbFJl
c29sdXRpb247DQorDQorICBpZiAoRW5hYmxlKSB7DQorICAgIERpc3BsYXktPkN1cnJlbnRNb2Rl
ID0gTW9kZU51bWJlcjsNCisNCisgICAgVmFsMzIgPSAoRGlzcGxheS0+SEFjdGl2ZSAtIDEpIDw8
IDE2Ow0KKyAgICBWYWwzMiB8PSBEaXNwbGF5LT5WQWN0aXZlOw0KKyAgICBSZWdXcml0ZTMyIChQ
cml2YXRlLCBQSVBFU1JDKFBJUEVfQSksIFZhbDMyKTsNCisNCisgICAgUmVnUmVhZDMyIChQcml2
YXRlLCBQSVBFX0NPTkYoUElQRV9BKSwgJlZhbDMyKTsNCisgICAgVmFsMzIgfD0gUElQRV9DT05G
X0VOQUJMRTsNCisgICAgUmVnV3JpdGUzMiAoUHJpdmF0ZSwgUElQRV9DT05GKFBJUEVfQSksIFZh
bDMyKTsNCisNCisgICAgVmFsMzIgPSAoV2lkdGggLSAxKSAmIDB4RkZGOw0KKyAgICBWYWwzMiB8
PSAoKEhlaWdodCAtIDEpICYgMHhGRkYpIDw8IDE2Ow0KKyAgICBSZWdXcml0ZTMyIChQcml2YXRl
LCBQTEFORV9TSVpFKFBJUEVfQSwgUExBTkVfUFJJTUFSWSksIFZhbDMyKTsNCisgICAgUmVnV3Jp
dGUzMiAoUHJpdmF0ZSwgUExBTkVfUE9TKFBJUEVfQSwgUExBTkVfUFJJTUFSWSksIDApOw0KKw0K
KyAgICAvLyBDb252ZXJ0IG1vZGUgd2l0aCB0byBzdHJpZGUgaW4gY2h1bmtzIG9mIDY0IGJ5dGVz
IGFzIHJlcXVpcmVkIGJ5IFBMQU5FX1NUUklERQ0KKyAgICBWYWwzMiA9IERpc3BsYXktPk1vZGVM
aXN0W01vZGVOdW1iZXJdLkhvcml6b250YWxSZXNvbHV0aW9uICogRGlzcGxheS0+QnBwOw0KKyAg
ICBWYWwzMiA9IEFMSUdOX1ZBTFVFIChWYWwzMiwgNjQpOw0KKyAgICBWYWwzMiA9IChWYWwzMiAv
IDY0KSAmIFBMQU5FX1NUUklERV9NQVNLOw0KKyAgICBSZWdXcml0ZTMyIChQcml2YXRlLCBQTEFO
RV9TVFJJREUoUElQRV9BLCBQTEFORV9QUklNQVJZKSwgVmFsMzIpOw0KKw0KKyAgICBSZWdXcml0
ZTMyIChQcml2YXRlLCBQTEFORV9TVVJGKFBJUEVfQSwgUExBTkVfUFJJTUFSWSksIERpc3BsYXkt
PkZiR01BZGRyKTsNCisNCisgICAgLy8gU3RyZXRjaCB0byBmdWxsc2NyZWVuIGlmIGN1cnJlbnQg
bW9kZSBpcyBzbWFsbGVyIHRoYW4gSC9WIGFjdGl2ZS4NCisgICAgaWYgKERpc3BsYXktPkhBY3Rp
dmUgIT0gV2lkdGggfHwNCisgICAgICAgIERpc3BsYXktPlZBY3RpdmUgIT0gSGVpZ2h0KSB7DQor
ICAgICAgUmVnV3JpdGUzMiAoUHJpdmF0ZSwgUFNfV0lOX1BPUyhQSVBFX0EsIDApLCAwKTsNCisg
ICAgICBSZWdXcml0ZTMyIChQcml2YXRlLA0KKyAgICAgICAgUFNfV0lOX1NaKFBJUEVfQSwgMCks
DQorICAgICAgICBEaXNwbGF5LT5IQWN0aXZlIDw8IDE2IHwgRGlzcGxheS0+VkFjdGl2ZQ0KKyAg
ICAgICAgKTsNCisgICAgICBSZWdSZWFkMzIgKFByaXZhdGUsIFBTX0NUUkwoUElQRV9BLCAwKSwg
JlZhbDMyKTsNCisgICAgICBWYWwzMiB8PSBQU19DVFJMX1NDQUxFUl9FTjsNCisgICAgICBWYWwz
MiAmPSB+UFNfQ1RSTF9TQ0FMRVJfTU9ERV9NQVNLOw0KKyAgICAgIFZhbDMyIHw9IFBTX0NUUkxf
U0NBTEVSX01PREVfRFlOOw0KKyAgICAgIFZhbDMyICY9IH5QU19DVFJMX1NDQUxFUl9CSU5ESU5H
X01BU0s7DQorICAgICAgVmFsMzIgfD0gUFNfQ1RSTF9QTEFORV9TRUwoUExBTkVfUFJJTUFSWSk7
DQorICAgICAgVmFsMzIgJj0gflBTX0NUUkxfU0NBTEVSX0ZJTFRFUl9NQVNLOw0KKyAgICAgIFZh
bDMyIHw9IFBTX0NUUkxfU0NBTEVSX0ZJTFRFUl9NRURJVU07DQorICAgICAgUmVnV3JpdGUzMiAo
UHJpdmF0ZSwgUFNfQ1RSTChQSVBFX0EsIDApLCBWYWwzMik7DQorICAgIH0NCisNCisgICAgUmVn
UmVhZDMyIChQcml2YXRlLCBQTEFORV9DVEwoUElQRV9BLCBQTEFORV9QUklNQVJZKSwgJlZhbDMy
KTsNCisgICAgVmFsMzIgfD0gUExBTkVfQ1RMX0VOQUJMRTsNCisgICAgVmFsMzIgJj0gflBMQU5F
X0NUTF9QSVBFX0dBTU1BX0VOQUJMRTsNCisgICAgVmFsMzIgJj0gflBMQU5FX0NUTF9GT1JNQVRf
TUFTSzsNCisgICAgVmFsMzIgfD0gUExBTkVfQ1RMX0ZPUk1BVF9YUkdCXzg4ODg7DQorICAgIFZh
bDMyICY9IH5QTEFORV9DVExfUElQRV9DU0NfRU5BQkxFOw0KKyAgICBWYWwzMiAmPSB+UExBTkVf
Q1RMX0tFWV9FTkFCTEVfTUFTSzsNCisgICAgVmFsMzIgJj0gflBMQU5FX0NUTF9PUkRFUl9SR0JY
Ow0KKyAgICBpZiAoRGlzcGxheS0+TW9kZUxpc3RbTW9kZU51bWJlcl0uUGl4ZWxGb3JtYXQgPT0g
UGl4ZWxSZWRHcmVlbkJsdWVSZXNlcnZlZDhCaXRQZXJDb2xvcikgew0KKyAgICAgIFZhbDMyIHw9
IFBMQU5FX0NUTF9PUkRFUl9SR0JYOw0KKyAgICB9DQorICAgIFZhbDMyICY9IH5QTEFORV9DVExf
UkVOREVSX0RFQ09NUFJFU1NJT05fRU5BQkxFOw0KKyAgICBWYWwzMiB8PSBQTEFORV9DVExfUExB
TkVfR0FNTUFfRElTQUJMRTsNCisgICAgVmFsMzIgJj0gflBMQU5FX0NUTF9USUxFRF9NQVNLOw0K
KyAgICBWYWwzMiB8PSBQTEFORV9DVExfVElMRURfTElORUFSOw0KKyAgICBWYWwzMiAmPSB+UExB
TkVfQ1RMX0FTWU5DX0ZMSVA7DQorICAgIFZhbDMyICY9IH5QTEFORV9DVExfQUxQSEFfTUFTSzsN
CisgICAgVmFsMzIgfD0gUExBTkVfQ1RMX0FMUEhBX0RJU0FCTEU7DQorICAgIFZhbDMyICY9IH5Q
TEFORV9DVExfUk9UQVRFX01BU0s7DQorICAgIFZhbDMyIHw9IFBMQU5FX0NUTF9ST1RBVEVfMDsN
CisgICAgUmVnV3JpdGUzMiAoUHJpdmF0ZSwgUExBTkVfQ1RMKFBJUEVfQSwgUExBTkVfUFJJTUFS
WSksIFZhbDMyKTsNCisgIH0gZWxzZSB7DQorICAgIERpc3BsYXktPkN1cnJlbnRNb2RlID0gRElT
UExBWV9NT0RFX0lOVkFMSUQ7DQorDQorICAgIFJlZ1JlYWQzMiAoUHJpdmF0ZSwgUExBTkVfQ1RM
KFBJUEVfQSwgUExBTkVfUFJJTUFSWSksICZWYWwzMik7DQorICAgIFZhbDMyICY9IH5QTEFORV9D
VExfRU5BQkxFOw0KKyAgICBSZWdXcml0ZTMyIChQcml2YXRlLCBQTEFORV9DVEwoUElQRV9BLCBQ
TEFORV9QUklNQVJZKSwgVmFsMzIpOw0KKyAgICBSZWdXcml0ZTMyIChQcml2YXRlLCBQTEFORV9T
VVJGKFBJUEVfQSwgUExBTkVfUFJJTUFSWSksIDApOw0KKw0KKyAgICBSZWdSZWFkMzIgKFByaXZh
dGUsIFBTX0NUUkwoUElQRV9BLCAwKSwgJlZhbDMyKTsNCisgICAgVmFsMzIgJj0gflBTX0NUUkxf
U0NBTEVSX0VOOw0KKyAgICBSZWdXcml0ZTMyIChQcml2YXRlLCBQU19DVFJMKFBJUEVfQSwgMCks
IFZhbDMyKTsNCisgICAgUmVnV3JpdGUzMiAoUHJpdmF0ZSwgUFNfV0lOX1BPUyhQSVBFX0EsIDAp
LCAwKTsNCisgICAgUmVnV3JpdGUzMiAoUHJpdmF0ZSwgUFNfV0lOX1NaKFBJUEVfQSwgMCksIDAp
Ow0KKw0KKyAgICBSZWdSZWFkMzIgKFByaXZhdGUsIFBJUEVfQ09ORihQSVBFX0EpLCAmVmFsMzIp
Ow0KKyAgICBWYWwzMiAmPSB+UElQRV9DT05GX0VOQUJMRTsNCisgICAgUmVnV3JpdGUzMiAoUHJp
dmF0ZSwgUElQRV9DT05GKFBJUEVfQSksIFZhbDMyKTsNCisgIH0NCisNCisgIFN0YXR1cyA9IEVG
SV9TVUNDRVNTOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWE6ICVhIG1vZGUg
JWR4JWQgMHgleCwgc2NhbGluZyAlYVxuIiwNCisgICAgX19GVU5DVElPTl9fLA0KKyAgICBFbmFi
bGUgPyAiRW5hYmxlIiA6ICJEaXNhYmxlIiwNCisgICAgV2lkdGgsDQorICAgIEhlaWdodCwNCisg
ICAgRGlzcGxheS0+RmJHTUFkZHIsDQorICAgIChEaXNwbGF5LT5IQWN0aXZlICE9IFdpZHRoIHx8
DQorICAgICBEaXNwbGF5LT5WQWN0aXZlICE9IEhlaWdodCkgPyAiT24iIDogIk9mZiIpOw0KKw0K
K0RvbmU6DQorDQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsICIlYTogPDw8XG4iLCBfX0ZV
TkNUSU9OX18pOw0KKw0KKyAgcmV0dXJuIFN0YXR1czsNCit9DQorDQorRUZJX1NUQVRVUw0KK0lu
dGVsVmlydHVhbEdwdU5vdGlmeURpc3BsYXlSZWFkeSAoDQorICBJTiBHVlRfR09QX1BSSVZBVEVf
REFUQSAqUHJpdmF0ZSwNCisgIElOIEJPT0xFQU4gICAgICAgICAgICAgIFJlYWR5DQorICApDQor
ew0KKyAgcmV0dXJuIFJlZ1dyaXRlMzIgKA0KKyAgICAgICAgICAgUHJpdmF0ZSwNCisgICAgICAg
ICAgIHZndGlmX3JlZyhkaXNwbGF5X3JlYWR5KSwNCisgICAgICAgICAgIFJlYWR5ID8gVkdUX0RS
Vl9ESVNQTEFZX1JFQURZIDogVkdUX0RSVl9ESVNQTEFZX05PVF9SRUFEWQ0KKyAgICAgICAgICAg
KTsNCit9DQorDQorRUZJX1NUQVRVUw0KK0ludGVsVmlydHVhbEdwdUJsdFZpZGVvRmlsbCAoDQor
ICBJTiBQSU5URUxfVklSVFVBTF9HUFVfRElTUExBWSAgICAgICAgICBEaXNwbGF5LA0KKyAgSU4g
RUZJX0dSQVBISUNTX09VVFBVVF9CTFRfUElYRUxfVU5JT04gQmx0UGl4ZWwsDQorICBJTiBCTFRf
UkVDVEFOR0xFICAgICAgICAgICAgICAgICAgICAgICBEZXN0aW5hdGlvbg0KKyAgKQ0KK3sNCisg
IEVGSV9TVEFUVVMgU3RhdHVzID0gRUZJX0lOVkFMSURfUEFSQU1FVEVSOw0KKyAgVk9JRCAgICAg
ICAqRGVzdEFkZHI7DQorICBVSU5UTiAgICAgIERlc3RCeXRlcywgTW9kZVN0cmlkZUJ5dGVzLCBM
aW5lOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWE6ID4+PlxuIiwgX19GVU5D
VElPTl9fKTsNCisNCisgIGlmIChEZXN0aW5hdGlvbi5XaWR0aCA9PSAwIHx8IERlc3RpbmF0aW9u
LkhlaWdodCA9PSAwKSB7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgIkVm
aUJsdFZpZGVvRmlsbCBpbnZhbGlkIGRlc3RpbmF0aW9uIHJlY3RhbmdsZSBbJWQsICVkXSBcbiIs
DQorICAgICAgRGVzdGluYXRpb24uV2lkdGgsIERlc3RpbmF0aW9uLkhlaWdodA0KKyAgICAgICk7
DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIGlmICgoRGVzdGluYXRpb24uWCArIERlc3Rp
bmF0aW9uLldpZHRoID4gRGlzcGxheS0+V2lkdGgpIHx8DQorICAgICAgKERlc3RpbmF0aW9uLlkg
KyBEZXN0aW5hdGlvbi5IZWlnaHQgPiBEaXNwbGF5LT5IZWlnaHQpKSB7DQorICAgIEdWVF9ERUJV
RyAoRUZJX0RfRVJST1IsDQorICAgICAgIkVmaUJsdFZpZGVvRmlsbCBkZXN0aW5hdGlvbiBbJWQs
ICVkXSB0byBbJWQsICVkXSBvdWYgb2YgcmFuZ2UgWyVkLCAlZF1cbiIsDQorICAgICAgRGVzdGlu
YXRpb24uWCwgRGVzdGluYXRpb24uWSwNCisgICAgICBEZXN0aW5hdGlvbi5YICsgRGVzdGluYXRp
b24uV2lkdGgsIERlc3RpbmF0aW9uLlkgKyBEZXN0aW5hdGlvbi5IZWlnaHQsDQorICAgICAgRGlz
cGxheS0+V2lkdGgsIERpc3BsYXktPkhlaWdodA0KKyAgICAgICk7DQorICAgIGdvdG8gRG9uZTsN
CisgIH0NCisNCisgIGlmIChEaXNwbGF5LT5DdXJyZW50TW9kZSA9PSBESVNQTEFZX01PREVfSU5W
QUxJRCkgew0KKyAgICBNb2RlU3RyaWRlQnl0ZXMgPSBEaXNwbGF5LT5XaWR0aDsNCisgIH0gZWxz
ZSB7DQorICAgIE1vZGVTdHJpZGVCeXRlcyA9IERpc3BsYXktPk1vZGVMaXN0W0Rpc3BsYXktPkN1
cnJlbnRNb2RlXS5Ib3Jpem9udGFsUmVzb2x1dGlvbjsNCisgIH0NCisgIE1vZGVTdHJpZGVCeXRl
cyA9IEFMSUdOX1ZBTFVFIChNb2RlU3RyaWRlQnl0ZXMgKiBEaXNwbGF5LT5CcHAsIDY0KTsNCisN
CisgIGlmIChEZXN0aW5hdGlvbi5XaWR0aCAqIERpc3BsYXktPkJwcCA9PSBNb2RlU3RyaWRlQnl0
ZXMpIHsNCisgICAgRGVzdEFkZHIgPSAoVUlOVDgqKURpc3BsYXktPkZiR01BZGRyICsgRGVzdGlu
YXRpb24uWSAqIE1vZGVTdHJpZGVCeXRlczsNCisgICAgRGVzdEJ5dGVzID0gRGVzdGluYXRpb24u
V2lkdGggKiBEaXNwbGF5LT5CcHAgKiBEZXN0aW5hdGlvbi5IZWlnaHQ7DQorICAgIFNldE1lbTMy
ICgoVk9JRCopRGVzdEFkZHIsIERlc3RCeXRlcywgQmx0UGl4ZWwuUmF3KTsNCisgIH0gZWxzZSB7
DQorDQorICAgIGZvciAoTGluZSA9IDA7IExpbmUgPCBEZXN0aW5hdGlvbi5IZWlnaHQ7IExpbmUr
Kykgew0KKyAgICAgIERlc3RBZGRyID0gKFVJTlQ4KilEaXNwbGF5LT5GYkdNQWRkciArDQorICAg
ICAgICAoTGluZSArIERlc3RpbmF0aW9uLlkpICogTW9kZVN0cmlkZUJ5dGVzICsNCisgICAgICAg
IERlc3RpbmF0aW9uLlggKiBEaXNwbGF5LT5CcHA7DQorICAgICAgRGVzdEJ5dGVzID0gRGVzdGlu
YXRpb24uV2lkdGggKiBEaXNwbGF5LT5CcHA7DQorDQorICAgICAgU2V0TWVtMzIgKERlc3RBZGRy
LCBEZXN0Qnl0ZXMsIEJsdFBpeGVsLlJhdyk7DQorICAgIH0NCisgIH0NCisNCisgIFN0YXR1cyA9
IEVGSV9TVUNDRVNTOw0KKw0KK0RvbmU6DQorDQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0Us
ICIlYTogPDw8XG4iLCBfX0ZVTkNUSU9OX18pOw0KKw0KKyAgcmV0dXJuIFN0YXR1czsNCit9DQor
DQorRUZJX1NUQVRVUw0KK0ludGVsVmlydHVhbEdwdUJsdFZpZGVvVG9CdWZmZXIgKA0KKyAgSU4g
UElOVEVMX1ZJUlRVQUxfR1BVX0RJU1BMQVkgICAgRGlzcGxheSwNCisgIElOIEVGSV9HUkFQSElD
U19PVVRQVVRfQkxUX1BJWEVMICpCbHRCdWZmZXIsDQorICBJTiBCTFRfUkVDVEFOR0xFICAgICAg
ICAgICAgICAgICBTb3VyY2UsDQorICBJTiBCTFRfUkVDVEFOR0xFICAgICAgICAgICAgICAgICBE
ZXN0aW5hdGlvbiwNCisgIElOIFVJTlROICAgICAgICAgICAgICAgICAgICAgICAgIERlbHRhDQor
ICApDQorew0KKyAgRUZJX1NUQVRVUyBTdGF0dXMgPSBFRklfSU5WQUxJRF9QQVJBTUVURVI7DQor
ICBWT0lEICAgICAgICpTb3VyY2VBZGRyLCAqRGVzdEFkZHI7DQorICBVSU5UTiAgICAgIERlc3RT
dHJpZGUsIENvcHlCeXRlcywgTW9kZVN0cmlkZUJ5dGVzLCBMaW5lOw0KKw0KKyAgR1ZUX0RFQlVH
IChFRklfRF9WRVJCT1NFLCAiJWE6ID4+PlxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIGlmIChT
b3VyY2UuV2lkdGggPT0gMCB8fCBTb3VyY2UuSGVpZ2h0ID09IDApIHsNCisgICAgR1ZUX0RFQlVH
IChFRklfRF9FUlJPUiwNCisgICAgICAiRWZpQmx0VmlkZW9Ub0JsdEJ1ZmZlciBpbnZhbGlkIHNv
dXJjZSByZWN0YW5nbGUgWyVkLCAlZF0gXG4iLA0KKyAgICAgIFNvdXJjZS5XaWR0aCwgU291cmNl
LkhlaWdodA0KKyAgICAgICk7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIGlmIChTb3Vy
Y2UuV2lkdGggIT0gRGVzdGluYXRpb24uV2lkdGggfHwNCisgICAgICBTb3VyY2UuSGVpZ2h0ICE9
IERlc3RpbmF0aW9uLkhlaWdodCkgew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9SLA0KKyAg
ICAgICJFZmlCbHRWaWRlb1RvQmx0QnVmZmVyIHNpemUgbWlzbWF0Y2g6IHNvdXJjZSAlZHglZCwg
ZGVzdGluYXRpb24gJWR4JWRcbiIsDQorICAgICAgU291cmNlLldpZHRoLCBTb3VyY2UuSGVpZ2h0
LCBEZXN0aW5hdGlvbi5XaWR0aCwgRGVzdGluYXRpb24uSGVpZ2h0DQorICAgICAgKTsNCisgICAg
Z290byBEb25lOw0KKyAgfQ0KKw0KKyAgaWYgKChTb3VyY2UuWCArIFNvdXJjZS5XaWR0aCA+IERp
c3BsYXktPldpZHRoKSB8fA0KKyAgICAgIChTb3VyY2UuWSArIFNvdXJjZS5IZWlnaHQgPiBEaXNw
bGF5LT5IZWlnaHQpKSB7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgIkVm
aUJsdFZpZGVvVG9CbHRCdWZmZXIgc291cmNlIFslZCwgJWRdIHRvIFslZCwgJWRdIG91ZiBvZiBy
YW5nZSBbJWQsICVkXVxuIiwNCisgICAgICBTb3VyY2UuWCwgU291cmNlLlksDQorICAgICAgU291
cmNlLlggKyBTb3VyY2UuV2lkdGgsIFNvdXJjZS5ZICsgU291cmNlLkhlaWdodCwNCisgICAgICBE
aXNwbGF5LT5XaWR0aCwgRGlzcGxheS0+SGVpZ2h0DQorICAgICAgKTsNCisgICAgZ290byBEb25l
Ow0KKyAgfQ0KKw0KKyAgaWYgKERlc3RpbmF0aW9uLlggIT0gMCB8fCBEZXN0aW5hdGlvbi5ZICE9
IDApIHsNCisgICAgRGVzdFN0cmlkZSA9IERlbHRhOw0KKyAgfSBlbHNlIHsNCisgICAgRGVzdFN0
cmlkZSA9IERlc3RpbmF0aW9uLldpZHRoICogRGlzcGxheS0+QnBwOw0KKyAgfQ0KKw0KKyAgaWYg
KERpc3BsYXktPkN1cnJlbnRNb2RlID09IERJU1BMQVlfTU9ERV9JTlZBTElEKSB7DQorICAgIE1v
ZGVTdHJpZGVCeXRlcyA9IERpc3BsYXktPldpZHRoOw0KKyAgfSBlbHNlIHsNCisgICAgTW9kZVN0
cmlkZUJ5dGVzID0gRGlzcGxheS0+TW9kZUxpc3RbRGlzcGxheS0+Q3VycmVudE1vZGVdLkhvcml6
b250YWxSZXNvbHV0aW9uOw0KKyAgfQ0KKyAgTW9kZVN0cmlkZUJ5dGVzID0gQUxJR05fVkFMVUUg
KE1vZGVTdHJpZGVCeXRlcyAqIERpc3BsYXktPkJwcCwgNjQpOw0KKw0KKyAgZm9yIChMaW5lID0g
MDsgTGluZSA8IFNvdXJjZS5IZWlnaHQ7IExpbmUrKykgew0KKyAgICBTb3VyY2VBZGRyID0gKFVJ
TlQ4KilEaXNwbGF5LT5GYkdNQWRkciArDQorICAgICAgKFNvdXJjZS5ZICsgTGluZSkgKiBNb2Rl
U3RyaWRlQnl0ZXMgKw0KKyAgICAgIFNvdXJjZS5YICogRGlzcGxheS0+QnBwOw0KKyAgICBEZXN0
QWRkciA9IChVSU5UOCopQmx0QnVmZmVyICsgKERlc3RpbmF0aW9uLlkgKyBMaW5lKSAqIERlc3RT
dHJpZGU7DQorICAgIERlc3RBZGRyID0gKFVJTlQ4KilEZXN0QWRkciArIERlc3RpbmF0aW9uLlgg
KiBEaXNwbGF5LT5CcHA7DQorICAgIENvcHlCeXRlcyA9IFNvdXJjZS5XaWR0aCAqIERpc3BsYXkt
PkJwcDsNCisgICAgQ29weU1lbSAoRGVzdEFkZHIsIFNvdXJjZUFkZHIsIENvcHlCeXRlcyk7DQor
ICB9DQorDQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsDQorICAgICJFZmlCbHRWaWRlb1Rv
Qmx0QnVmZmVyIFslZCwgJWRdID4+IFslZCwgJWRdIHNpemUgWyVkLCAlZF0gRGVsdGEgJWRcbiIs
DQorICAgIFNvdXJjZS5YLCBTb3VyY2UuWSwNCisgICAgRGVzdGluYXRpb24uWCwgRGVzdGluYXRp
b24uWSwNCisgICAgU291cmNlLldpZHRoLCBTb3VyY2UuSGVpZ2h0LA0KKyAgICBEZWx0YQ0KKyAg
ICApOw0KKw0KKyAgU3RhdHVzID0gRUZJX1NVQ0NFU1M7DQorDQorRG9uZToNCisNCisgIEdWVF9E
RUJVRyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA8PDxcbiIsIF9fRlVOQ1RJT05fXyk7DQorDQorICBy
ZXR1cm4gU3RhdHVzOw0KK30NCisNCitFRklfU1RBVFVTDQorSW50ZWxWaXJ0dWFsR3B1Qmx0Vmlk
ZW9Gcm9tQnVmZmVyICgNCisgIElOIFBJTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZICAgIERpc3Bs
YXksDQorICBJTiBFRklfR1JBUEhJQ1NfT1VUUFVUX0JMVF9QSVhFTCAqQmx0QnVmZmVyLA0KKyAg
SU4gQkxUX1JFQ1RBTkdMRSAgICAgICAgICAgICAgICAgU291cmNlLA0KKyAgSU4gQkxUX1JFQ1RB
TkdMRSAgICAgICAgICAgICAgICAgRGVzdGluYXRpb24sDQorICBJTiBVSU5UTiAgICAgICAgICAg
ICAgICAgICAgICAgICBEZWx0YQ0KKyAgKQ0KK3sNCisgIEVGSV9TVEFUVVMgU3RhdHVzID0gRUZJ
X0lOVkFMSURfUEFSQU1FVEVSOw0KKyAgVk9JRCAgICAgICAqU291cmNlQWRkciwgKkRlc3RBZGRy
Ow0KKyAgVUlOVE4gICAgICBTb3VyY2VTdHJpZGUsIENvcHlCeXRlcywgTW9kZVN0cmlkZUJ5dGVz
LCBMaW5lOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWE6ID4+PlxuIiwgX19G
VU5DVElPTl9fKTsNCisNCisgIGlmIChTb3VyY2UuV2lkdGggPT0gMCB8fCBTb3VyY2UuSGVpZ2h0
ID09IDApIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiRWZpQmx0QnVm
ZmVyVG9WaWRlbyBpbnZhbGlkIHNvdXJjZSByZWN0YW5nbGUgWyVkLCAlZF0gXG4iLA0KKyAgICAg
IFNvdXJjZS5XaWR0aCwgU291cmNlLkhlaWdodA0KKyAgICAgICk7DQorICAgIGdvdG8gRG9uZTsN
CisgIH0NCisNCisgIGlmIChTb3VyY2UuV2lkdGggIT0gRGVzdGluYXRpb24uV2lkdGggfHwgU291
cmNlLkhlaWdodCAhPSBEZXN0aW5hdGlvbi5IZWlnaHQpIHsNCisgICAgR1ZUX0RFQlVHIChFRklf
RF9FUlJPUiwNCisgICAgICAiRWZpQmx0QnVmZmVyVG9WaWRlbyBzaXplIG1pc21hdGNoOiBzb3Vy
Y2UgJWR4JWQsIGRlc3RpbmF0aW9uICVkeCVkXG4iLA0KKyAgICAgIFNvdXJjZS5XaWR0aCwgU291
cmNlLkhlaWdodCwgRGVzdGluYXRpb24uV2lkdGgsIERlc3RpbmF0aW9uLkhlaWdodA0KKyAgICAg
ICk7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIGlmICgoRGVzdGluYXRpb24uWCArIERl
c3RpbmF0aW9uLldpZHRoID4gRGlzcGxheS0+V2lkdGgpIHx8DQorICAgICAgKERlc3RpbmF0aW9u
LlkgKyBEZXN0aW5hdGlvbi5IZWlnaHQgPiBEaXNwbGF5LT5IZWlnaHQpKSB7DQorICAgIEdWVF9E
RUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgIkVmaUJsdEJ1ZmZlclRvVmlkZW8gZGVzdGluYXRp
b24gWyVkLCAlZF0gdG8gWyVkLCAlZF0gb3VmIG9mIHJhbmdlIFslZCwgJWRdXG4iLA0KKyAgICAg
IERlc3RpbmF0aW9uLlgsIERlc3RpbmF0aW9uLlksDQorICAgICAgRGVzdGluYXRpb24uWCArIERl
c3RpbmF0aW9uLldpZHRoLCBEZXN0aW5hdGlvbi5ZICsgRGVzdGluYXRpb24uSGVpZ2h0LA0KKyAg
ICAgIERpc3BsYXktPldpZHRoLCBEaXNwbGF5LT5IZWlnaHQNCisgICAgICApOw0KKyAgICBnb3Rv
IERvbmU7DQorICB9DQorDQorICBpZiAoU291cmNlLlggIT0gMCB8fCBTb3VyY2UuWSAhPSAwKSB7
DQorICAgIFNvdXJjZVN0cmlkZSA9IERlbHRhOw0KKyAgfSBlbHNlIHsNCisgICAgU291cmNlU3Ry
aWRlID0gU291cmNlLldpZHRoICogRGlzcGxheS0+QnBwOw0KKyAgfQ0KKw0KKyAgaWYgKERpc3Bs
YXktPkN1cnJlbnRNb2RlID09IERJU1BMQVlfTU9ERV9JTlZBTElEKSB7DQorICAgIE1vZGVTdHJp
ZGVCeXRlcyA9IERpc3BsYXktPldpZHRoOw0KKyAgfSBlbHNlIHsNCisgICAgTW9kZVN0cmlkZUJ5
dGVzID0gRGlzcGxheS0+TW9kZUxpc3RbRGlzcGxheS0+Q3VycmVudE1vZGVdLkhvcml6b250YWxS
ZXNvbHV0aW9uOw0KKyAgfQ0KKyAgTW9kZVN0cmlkZUJ5dGVzID0gQUxJR05fVkFMVUUgKE1vZGVT
dHJpZGVCeXRlcyAqIERpc3BsYXktPkJwcCwgNjQpOw0KKw0KKyAgZm9yIChMaW5lID0gMDsgTGlu
ZSA8IFNvdXJjZS5IZWlnaHQ7IExpbmUrKykgew0KKyAgICBTb3VyY2VBZGRyID0gKFVJTlQ4KilC
bHRCdWZmZXIgKw0KKyAgICAgIChTb3VyY2UuWSArIExpbmUpICogU291cmNlU3RyaWRlICsNCisg
ICAgICBTb3VyY2UuWCAqIERpc3BsYXktPkJwcDsNCisgICAgRGVzdEFkZHIgPSAoVUlOVDgqKURp
c3BsYXktPkZiR01BZGRyICsNCisgICAgICAoRGVzdGluYXRpb24uWSArIExpbmUpICogTW9kZVN0
cmlkZUJ5dGVzICsNCisgICAgICBEZXN0aW5hdGlvbi5YICogRGlzcGxheS0+QnBwOw0KKyAgICBD
b3B5Qnl0ZXMgPSBTb3VyY2UuV2lkdGggKiBEaXNwbGF5LT5CcHA7DQorICAgIENvcHlNZW0gKERl
c3RBZGRyLCBTb3VyY2VBZGRyLCBDb3B5Qnl0ZXMpOw0KKyAgfQ0KKw0KKyAgR1ZUX0RFQlVHIChF
RklfRF9WRVJCT1NFLCAiRWZpQmx0QnVmZmVyVG9WaWRlbyBbJWQsICVkXSA+PiBbJWQsICVkXSBz
aXplIFslZCwgJWRdIERlbHRhICVkXG4iLA0KKyAgICBTb3VyY2UuWCwgU291cmNlLlksDQorICAg
IERlc3RpbmF0aW9uLlgsIERlc3RpbmF0aW9uLlksDQorICAgIFNvdXJjZS5XaWR0aCwgU291cmNl
LkhlaWdodCwNCisgICAgRGVsdGENCisgICAgKTsNCisNCisgIFN0YXR1cyA9IEVGSV9TVUNDRVNT
Ow0KKw0KK0RvbmU6DQorDQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsICIlYTogPDw8XG4i
LCBfX0ZVTkNUSU9OX18pOw0KKw0KKyAgcmV0dXJuIFN0YXR1czsNCit9DQorDQorRUZJX1NUQVRV
Uw0KK0ludGVsVmlydHVhbEdwdUJsdFZpZGVvVG9WaWRlbyAoDQorICBJTiBQSU5URUxfVklSVFVB
TF9HUFVfRElTUExBWSBEaXNwbGF5LA0KKyAgSU4gQkxUX1JFQ1RBTkdMRSAgICAgICAgICAgICAg
U291cmNlLA0KKyAgSU4gQkxUX1JFQ1RBTkdMRSAgICAgICAgICAgICAgRGVzdGluYXRpb24NCisg
ICkNCit7DQorICBFRklfU1RBVFVTIFN0YXR1cyA9IEVGSV9JTlZBTElEX1BBUkFNRVRFUjsNCisg
IFZPSUQgICAgICAgKlNvdXJjZUFkZHIsICpEZXN0QWRkcjsNCisgIFVJTlROICAgICAgQ29weUJ5
dGVzLCBNb2RlU3RyaWRlQnl0ZXMsIExpbmU7DQorDQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJP
U0UsICIlYTogPj4+XG4iLCBfX0ZVTkNUSU9OX18pOw0KKw0KKyAgaWYgKFNvdXJjZS5XaWR0aCA9
PSAwIHx8IFNvdXJjZS5IZWlnaHQgPT0gMCkgew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9S
LA0KKyAgICAgICJFZmlCbHRWaWRlb1RvVmlkZW8gaW52YWxpZCBzb3VyY2UgcmVjdGFuZ2xlIFsl
ZCwgJWRdIFxuIiwNCisgICAgICBTb3VyY2UuV2lkdGgsIFNvdXJjZS5IZWlnaHQNCisgICAgICAp
Ow0KKyAgICBnb3RvIERvbmU7DQorICB9DQorDQorICBpZiAoU291cmNlLldpZHRoICE9IERlc3Rp
bmF0aW9uLldpZHRoIHx8IFNvdXJjZS5IZWlnaHQgIT0gRGVzdGluYXRpb24uSGVpZ2h0KSB7DQor
ICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgIkVmaUJsdFZpZGVvVG9WaWRlbyBz
aXplIG1pc21hdGNoOiBzb3VyY2UgJWR4JWQsIGRlc3RpbmF0aW9uICVkeCVkXG4iLA0KKyAgICAg
IFNvdXJjZS5XaWR0aCwgU291cmNlLkhlaWdodCwgRGVzdGluYXRpb24uV2lkdGgsIERlc3RpbmF0
aW9uLkhlaWdodA0KKyAgICAgICk7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIGlmICgo
U291cmNlLlggKyBTb3VyY2UuV2lkdGggPiBEaXNwbGF5LT5XaWR0aCkgfHwNCisgICAgICAoU291
cmNlLlkgKyBTb3VyY2UuSGVpZ2h0ID4gRGlzcGxheS0+SGVpZ2h0KSkgew0KKyAgICBHVlRfREVC
VUcgKEVGSV9EX0VSUk9SLA0KKyAgICAgICJFZmlCbHRWaWRlb1RvVmlkZW8gc291cmNlIFslZCwg
JWRdIHRvIFslZCwgJWRdIG91ZiBvZiByYW5nZSBbJWQsICVkXVxuIiwNCisgICAgICBTb3VyY2Uu
WCwgU291cmNlLlksDQorICAgICAgU291cmNlLlggKyBTb3VyY2UuV2lkdGgsIFNvdXJjZS5ZICsg
U291cmNlLkhlaWdodCwNCisgICAgICBEaXNwbGF5LT5XaWR0aCwgRGlzcGxheS0+SGVpZ2h0DQor
ICAgICAgKTsNCisgICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyAgaWYgKChEZXN0aW5hdGlvbi5Y
ICsgRGVzdGluYXRpb24uV2lkdGggPiBEaXNwbGF5LT5XaWR0aCkgfHwNCisgICAgICAoRGVzdGlu
YXRpb24uWSArIERlc3RpbmF0aW9uLkhlaWdodCA+IERpc3BsYXktPkhlaWdodCkpIHsNCisgICAg
R1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiRWZpQmx0VmlkZW9Ub1ZpZGVvIGRlc3Rp
bmF0aW9uIFslZCwgJWRdIHRvIFslZCwgJWRdIG91ZiBvZiByYW5nZSBbJWQsICVkXVxuIiwNCisg
ICAgICBEZXN0aW5hdGlvbi5YLCBEZXN0aW5hdGlvbi5ZLA0KKyAgICAgIERlc3RpbmF0aW9uLlgg
KyBEZXN0aW5hdGlvbi5XaWR0aCwgRGVzdGluYXRpb24uWSArIERlc3RpbmF0aW9uLkhlaWdodCwN
CisgICAgICBEaXNwbGF5LT5XaWR0aCwgRGlzcGxheS0+SGVpZ2h0DQorICAgICAgKTsNCisgICAg
Z290byBEb25lOw0KKyAgfQ0KKw0KKyAgaWYgKERpc3BsYXktPkN1cnJlbnRNb2RlID09IERJU1BM
QVlfTU9ERV9JTlZBTElEKSB7DQorICAgIE1vZGVTdHJpZGVCeXRlcyA9IERpc3BsYXktPldpZHRo
Ow0KKyAgfSBlbHNlIHsNCisgICAgTW9kZVN0cmlkZUJ5dGVzID0gRGlzcGxheS0+TW9kZUxpc3Rb
RGlzcGxheS0+Q3VycmVudE1vZGVdLkhvcml6b250YWxSZXNvbHV0aW9uOw0KKyAgfQ0KKyAgTW9k
ZVN0cmlkZUJ5dGVzID0gQUxJR05fVkFMVUUgKE1vZGVTdHJpZGVCeXRlcyAqIERpc3BsYXktPkJw
cCwgNjQpOw0KKw0KKyAgZm9yIChMaW5lID0gMDsgTGluZSA8IFNvdXJjZS5IZWlnaHQ7IExpbmUr
Kykgew0KKyAgICBTb3VyY2VBZGRyID0gKFVJTlQ4KilEaXNwbGF5LT5GYkdNQWRkciArDQorICAg
ICAgKFNvdXJjZS5ZICsgTGluZSkgKiBNb2RlU3RyaWRlQnl0ZXMgKw0KKyAgICAgIFNvdXJjZS5Y
ICogRGlzcGxheS0+QnBwOw0KKyAgICBEZXN0QWRkciA9IChVSU5UOCopRGlzcGxheS0+RmJHTUFk
ZHIgKw0KKyAgICAgIChEZXN0aW5hdGlvbi5ZICsgTGluZSkqIE1vZGVTdHJpZGVCeXRlcyArDQor
ICAgICAgRGVzdGluYXRpb24uWCAqIERpc3BsYXktPkJwcDsNCisgICAgQ29weUJ5dGVzID0gU291
cmNlLldpZHRoICogRGlzcGxheS0+QnBwOw0KKyAgICAvLw0KKyAgICAvLyBPdmVybGFwIGNvdWxk
IGNvcnJ1cHQgc291cmNlIGNvbnRlbnQ6DQorICAgIC8vIHNyYyA8LS0tLXwtLS0tPg0KKyAgICAv
LyBkc3QgICAgICA8LS0tLXwtLS0tPg0KKyAgICAvLw0KKyAgICBpZiAoRGVzdEFkZHIgPiBTb3Vy
Y2VBZGRyICYmIERlc3RBZGRyIDwgKFNvdXJjZUFkZHIgKyBDb3B5Qnl0ZXMpKSB7DQorICAgICAg
Q29weU1lbSAoDQorICAgICAgICBTb3VyY2VBZGRyICsgQ29weUJ5dGVzLA0KKyAgICAgICAgRGVz
dEFkZHIsDQorICAgICAgICBTb3VyY2VBZGRyICsgQ29weUJ5dGVzIC0gRGVzdEFkZHINCisgICAg
ICAgICk7DQorICAgICAgQ29weU1lbSAoRGVzdEFkZHIsIFNvdXJjZUFkZHIsIERlc3RBZGRyIC0g
U291cmNlQWRkcik7DQorICAgIC8vDQorICAgIC8vIE92ZXJsYXAgd29uJ3QgY29ycnVwdCBzb3Vy
Y2UgY29udGVudDoNCisgICAgLy8gc3JjICAgICAgPC0tLS18LS0tLT4NCisgICAgLy8gZHN0IDwt
LS0tfC0tLS0+DQorICAgIC8vDQorICAgIC8vIE5vIG92ZXJsYXANCisgICAgLy8gc3JjIDwtLS0t
LS0tLS0+DQorICAgIC8vIGRzdCAgICAgICAgICAgICAgICAgICAgICAgICA8LS0tLS0tLS0tPg0K
KyAgICAvLw0KKyAgICB9IGVsc2Ugew0KKyAgICAgIENvcHlNZW0gKERlc3RBZGRyLCBTb3VyY2VB
ZGRyLCBDb3B5Qnl0ZXMpOw0KKyAgICB9DQorICB9DQorDQorICBTdGF0dXMgPSBFRklfU1VDQ0VT
UzsNCisNCitEb25lOg0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWE6IDw8PFxu
IiwgX19GVU5DVElPTl9fKTsNCisNCisgIHJldHVybiBTdGF0dXM7DQorfQ0KZGlmZiAtLWdpdCBh
L092bWZQa2cvSW50ZWxHdnRHb3BEeGUvRGlzcGxheS5oIGIvT3ZtZlBrZy9JbnRlbEd2dEdvcER4
ZS9EaXNwbGF5LmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi4xOWU0
ZDY0ZjNiMTIKLS0tIC9kZXYvbnVsbAorKysgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL0Rpc3Bs
YXkuaApAQCAtMCwwICsxLDE0MSBAQAorLyoqIEBmaWxlDQorICBDb21wb25lbnQgbmFtZSBmb3Ig
dGhlIFFFTVUgdmlkZW8gY29udHJvbGxlci4NCisNCisgIENvcHlyaWdodCAoYykgMjAyMSwgSW50
ZWwgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuPEJSPg0KKw0KKyAgU1BEWC1MaWNl
bnNlLUlkZW50aWZpZXI6IEJTRC0yLUNsYXVzZS1QYXRlbnQNCisNCisqKi8NCisNCisjaWZuZGVm
IF9fRElTUExBWV9IXw0KKyNkZWZpbmUgX19ESVNQTEFZX0hfDQorDQorI2luY2x1ZGUgPExpYnJh
cnkvRnJhbWVCdWZmZXJCbHRMaWIuaD4NCisNCit0eXBlZGVmIHN0cnVjdCBfQkxUX1JFQ1RBTkdM
RSB7DQorICBVSU5UTiBYOw0KKyAgVUlOVE4gWTsNCisgIFVJTlROIFdpZHRoOw0KKyAgVUlOVE4g
SGVpZ2h0Ow0KK30gQkxUX1JFQ1RBTkdMRSwgKlBCTFRfUkVDVEFOR0xFOw0KKw0KKyNkZWZpbmUg
RElTUExBWV9XSURUSF9NQVggICAgICAxOTIwDQorI2RlZmluZSBESVNQTEFZX0hFSUdIVF9NQVgg
ICAgIDEwODANCisjZGVmaW5lIERJU1BMQVlfV0lEVEhfREVGQVVMVCAgMTAyNA0KKyNkZWZpbmUg
RElTUExBWV9IRUlHSFRfREVGQVVMVCA3NjgNCisjZGVmaW5lIERJU1BMQVlfTU9ERV9JTlZBTElE
ICAgMHhGRkZGDQorDQorI2RlZmluZSBESVNQTEFZX1VTRV9JTlRFUk5BTF9CTFQgMQ0KKw0KK3R5
cGVkZWYgc3RydWN0IF9JTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZIHsNCisgIFVJTlROICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBIQWN0aXZlOw0KKyAgVUlOVE4gICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgIFZBY3RpdmU7DQorICBVSU5UTiAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgV2lkdGg7DQorICBVSU5UTiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgSGVpZ2h0Ow0KKyAgVUlOVE4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdpZHRo
Qnl0ZXM7DQorICBVSU5UTiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RyaWRlQnl0
ZXM7DQorICBFRklfR1JBUEhJQ1NfUElYRUxfRk9STUFUICAgICAgICAgICAgRm9ybWF0Ow0KKyAg
VUlOVE4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJwcDsNCisgIFVJTlROICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBNYXhNb2RlOw0KKyAgVUlOVE4gICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgIEN1cnJlbnRNb2RlOw0KKyAgVUlOVE4gICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIEZiU2l6ZTsNCisgIFVJTlROICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICBQYWdlczsNCisgIEVGSV9QSFlTSUNBTF9BRERSRVNTICAgICAgICAgICAgICAgICBG
YkdNQWRkcjsNCisgIEVGSV9QSFlTSUNBTF9BRERSRVNTICAgICAgICAgICAgICAgICBGYlBoeXNp
Y2FsQWRkcjsNCisgIEVGSV9HUkFQSElDU19PVVRQVVRfTU9ERV9JTkZPUk1BVElPTiAqTW9kZUxp
c3Q7DQorICBGUkFNRV9CVUZGRVJfQ09ORklHVVJFICAgICAgICAgICAgICAgKkZyYW1lQnVmZmVy
Qmx0Q29uZmlndXJlOw0KKyAgVUlOVE4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZy
YW1lQnVmZmVyQmx0Q29uZmlndXJlU2l6ZTsNCit9IElOVEVMX1ZJUlRVQUxfR1BVX0RJU1BMQVks
ICpQSU5URUxfVklSVFVBTF9HUFVfRElTUExBWTsNCisNCitFRklfU1RBVFVTDQorSW50ZWxWaXJ0
dWFsR3B1RGlzcGxheUluaXQgKA0KKyAgSU4gT1VUIEdWVF9HT1BfUFJJVkFURV9EQVRBICpQcml2
YXRlDQorICApOw0KKw0KK0VGSV9TVEFUVVMNCitJbnRlbFZpcnR1YWxHcHVEaXNwbGF5Q2xlYW4g
KA0KKyAgSU4gT1VUIEdWVF9HT1BfUFJJVkFURV9EQVRBICpQcml2YXRlDQorICApOw0KKw0KK0VG
SV9TVEFUVVMNCitFRklBUEkNCitJbnRlbFZpcnR1YWxHcHVRdWVyeU1vZGUgKA0KKyAgSU4gIEVG
SV9HUkFQSElDU19PVVRQVVRfUFJPVE9DT0wgICAgICAgICAqVGhpcywNCisgIElOICBVSU5UMzIg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTW9kZU51bWJlciwNCisgIE9VVCBVSU5UTiAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlNpemVPZkluZm8sDQorICBPVVQgRUZJX0dS
QVBISUNTX09VVFBVVF9NT0RFX0lORk9STUFUSU9OICoqSW5mbw0KKyAgKTsNCisNCitFRklfU1RB
VFVTDQorRUZJQVBJDQorSW50ZWxWaXJ0dWFsR3B1U2V0TW9kZSAoDQorICBJTiBFRklfR1JBUEhJ
Q1NfT1VUUFVUX1BST1RPQ09MICpUaGlzLA0KKyAgSU4gVUlOVDMyICAgICAgICAgICAgICAgICAg
ICAgICBNb2RlTnVtYmVyDQorICApOw0KKw0KK0VGSV9TVEFUVVMNCitFRklBUEkNCitJbnRlbFZp
cnR1YWxHcHVCbHQgKA0KKyAgSU4gRUZJX0dSQVBISUNTX09VVFBVVF9QUk9UT0NPTCAgICAgICpU
aGlzLA0KKyAgSU4gRUZJX0dSQVBISUNTX09VVFBVVF9CTFRfUElYRUwgICAgICpCbHRCdWZmZXIs
ICAgT1BUSU9OQUwNCisgIElOIEVGSV9HUkFQSElDU19PVVRQVVRfQkxUX09QRVJBVElPTiBCbHRP
cGVyYXRpb24sDQorICBJTiBVSU5UTiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU291cmNl
WCwNCisgIElOIFVJTlROICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTb3VyY2VZLA0KKyAg
SU4gVUlOVE4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlc3RpbmF0aW9uWCwNCisgIElO
IFVJTlROICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZXN0aW5hdGlvblksDQorICBJTiBV
SU5UTiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV2lkdGgsDQorICBJTiBVSU5UTiAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgSGVpZ2h0LA0KKyAgSU4gVUlOVE4gICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIERlbHRhICAgICAgICAgT1BUSU9OQUwNCisgICk7DQorDQorRUZJX1NU
QVRVUw0KK0ludGVsVmlydHVhbEdwdUVuYWJsZURpc3BsYXkgKA0KKyAgSU4gT1VUIEdWVF9HT1Bf
UFJJVkFURV9EQVRBICpQcml2YXRlLA0KKyAgSU4gICAgIFVJTlQzMiAgICAgICAgICAgICAgIE1v
ZGVOdW1iZXIsDQorICBJTiAgICAgQk9PTEVBTiAgICAgICAgICAgICAgRW5hYmxlDQorICApOw0K
Kw0KK0VGSV9TVEFUVVMNCitJbnRlbFZpcnR1YWxHcHVOb3RpZnlEaXNwbGF5UmVhZHkgKA0KKyAg
SU4gR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlByaXZhdGUsDQorICBJTiBCT09MRUFOICAgICAgICAg
ICAgICBSZWFkeQ0KKyAgKTsNCisNCitFRklfU1RBVFVTDQorSW50ZWxWaXJ0dWFsR3B1Qmx0Vmlk
ZW9GaWxsICgNCisgIElOIFBJTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZICAgICAgICAgIERpc3Bs
YXksDQorICBJTiBFRklfR1JBUEhJQ1NfT1VUUFVUX0JMVF9QSVhFTF9VTklPTiBCbHRQaXhlbCwN
CisgIElOIEJMVF9SRUNUQU5HTEUgICAgICAgICAgICAgICAgICAgICAgIERlc3RpbmF0aW9uDQor
ICApOw0KKw0KK0VGSV9TVEFUVVMNCitJbnRlbFZpcnR1YWxHcHVCbHRWaWRlb1RvQnVmZmVyICgN
CisgIElOIFBJTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZICAgIERpc3BsYXksDQorICBJTiBFRklf
R1JBUEhJQ1NfT1VUUFVUX0JMVF9QSVhFTCAqQmx0QnVmZmVyLA0KKyAgSU4gQkxUX1JFQ1RBTkdM
RSAgICAgICAgICAgICAgICAgU291cmNlLA0KKyAgSU4gQkxUX1JFQ1RBTkdMRSAgICAgICAgICAg
ICAgICAgRGVzdGluYXRpb24sDQorICBJTiBVSU5UTiAgICAgICAgICAgICAgICAgICAgICAgICBE
ZWx0YQ0KKyAgKTsNCisNCitFRklfU1RBVFVTDQorSW50ZWxWaXJ0dWFsR3B1Qmx0VmlkZW9Gcm9t
QnVmZmVyICgNCisgIElOIFBJTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZICAgIERpc3BsYXksDQor
ICBJTiBFRklfR1JBUEhJQ1NfT1VUUFVUX0JMVF9QSVhFTCAqQmx0QnVmZmVyLA0KKyAgSU4gQkxU
X1JFQ1RBTkdMRSAgICAgICAgICAgICAgICAgU291cmNlLA0KKyAgSU4gQkxUX1JFQ1RBTkdMRSAg
ICAgICAgICAgICAgICAgRGVzdGluYXRpb24sDQorICBJTiBVSU5UTiAgICAgICAgICAgICAgICAg
ICAgICAgICBEZWx0YQ0KKyAgKTsNCisNCitFRklfU1RBVFVTDQorSW50ZWxWaXJ0dWFsR3B1Qmx0
VmlkZW9Ub1ZpZGVvICgNCisgIElOIFBJTlRFTF9WSVJUVUFMX0dQVV9ESVNQTEFZIERpc3BsYXks
DQorICBJTiBCTFRfUkVDVEFOR0xFICAgICAgICAgICAgICBTb3VyY2UsDQorICBJTiBCTFRfUkVD
VEFOR0xFICAgICAgICAgICAgICBEZXN0aW5hdGlvbg0KKyAgKTsNCitWT0lEDQorSW5zdGFsbFZi
ZVNoaW0gKA0KKyAgSU4gQ09OU1QgQ0hBUjE2ICAgICAgICAgKkNhcmROYW1lLA0KKyAgSU4gRUZJ
X1BIWVNJQ0FMX0FERFJFU1MgRnJhbWVCdWZmZXJCYXNlDQorICApOw0KKw0KKyNlbmRpZiAvL19f
RElTUExBWV9IXw0KZGlmZiAtLWdpdCBhL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvR29wRHJpdmVy
LmMgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL0dvcERyaXZlci5jCm5ldyBmaWxlIG1vZGUgMTAw
NjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uMzk2ZTVjZjQ0NDdjCi0tLSAvZGV2L251bGwKKysrIGIv
T3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9Hb3BEcml2ZXIuYwpAQCAtMCwwICsxLDQ3OCBAQAorLyoq
IEBmaWxlDQorICBDb21wb25lbnQgbmFtZSBmb3IgdGhlIFFFTVUgdmlkZW8gY29udHJvbGxlci4N
CisNCisgIENvcHlyaWdodCAoYykgMjAyMSwgSW50ZWwgQ29ycG9yYXRpb24uIEFsbCByaWdodHMg
cmVzZXJ2ZWQuPEJSPg0KKw0KKyAgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEJTRC0yLUNsYXVz
ZS1QYXRlbnQNCisNCisqKi8NCisNCisjaW5jbHVkZSAiQ29tbW9uLmgiDQorI2luY2x1ZGUgIlZp
cnR1YWxHcHUuaCINCisNCitFRklfU1RBVFVTDQorRUZJQVBJDQorR3Z0R29wQ29tcG9uZW50TmFt
ZUdldERyaXZlck5hbWUgKA0KKyAgSU4gIEVGSV9DT01QT05FTlRfTkFNRV9QUk9UT0NPTCAgKlRo
aXMsDQorICBJTiAgQ0hBUjggICAgICAgICAgICAgICAgICAgICAgICAqTGFuZ3VhZ2UsDQorICBP
VVQgQ0hBUjE2ICAgICAgICAgICAgICAgICAgICAgICAqKkRyaXZlck5hbWUNCisgICk7DQorDQor
RUZJX1NUQVRVUw0KK0VGSUFQSQ0KK0d2dEdvcENvbXBvbmVudE5hbWVHZXRDb250cm9sbGVyTmFt
ZSAoDQorICBJTiAgRUZJX0NPTVBPTkVOVF9OQU1FX1BST1RPQ09MICpUaGlzLA0KKyAgSU4gIEVG
SV9IQU5ETEUgICAgICAgICAgICAgICAgICBDb250cm9sbGVySGFuZGxlLA0KKyAgSU4gIEVGSV9I
QU5ETEUgICAgICAgICAgICAgICAgICBDaGlsZEhhbmRsZSBPUFRJT05BTCwNCisgIElOICBDSEFS
OCAgICAgICAgICAgICAgICAgICAgICAgKkxhbmd1YWdlLA0KKyAgT1VUIENIQVIxNiAgICAgICAg
ICAgICAgICAgICAgICAqKkNvbnRyb2xsZXJOYW1lDQorICApOw0KKw0KK0dMT0JBTF9SRU1PVkVf
SUZfVU5SRUZFUkVOQ0VEDQorRUZJX0NPTVBPTkVOVF9OQU1FX1BST1RPQ09MIGdHdnRHb3BEcml2
ZXJDb21wb25lbnROYW1lID0gew0KKyAgR3Z0R29wQ29tcG9uZW50TmFtZUdldERyaXZlck5hbWUs
DQorICBHdnRHb3BDb21wb25lbnROYW1lR2V0Q29udHJvbGxlck5hbWUsDQorICAiZW5nIg0KK307
DQorDQorR0xPQkFMX1JFTU9WRV9JRl9VTlJFRkVSRU5DRUQNCitFRklfQ09NUE9ORU5UX05BTUUy
X1BST1RPQ09MIGdHdnRHb3BEcml2ZXJDb21wb25lbnROYW1lMiA9IHsNCisgIChFRklfQ09NUE9O
RU5UX05BTUUyX0dFVF9EUklWRVJfTkFNRSkgR3Z0R29wQ29tcG9uZW50TmFtZUdldERyaXZlck5h
bWUsDQorICAoRUZJX0NPTVBPTkVOVF9OQU1FMl9HRVRfQ09OVFJPTExFUl9OQU1FKSBHdnRHb3BD
b21wb25lbnROYW1lR2V0Q29udHJvbGxlck5hbWUsDQorICAiZW4iDQorfTsNCisNCisNCitHTE9C
QUxfUkVNT1ZFX0lGX1VOUkVGRVJFTkNFRA0KK0VGSV9VTklDT0RFX1NUUklOR19UQUJMRSBnR3Z0
R29wRHJpdmVyTmFtZVRhYmxlW10gPSB7DQorICB7ICJlbmc7ZW4iLCBMIkludGVsIEdWVC1nIEdP
UCBEcml2ZXIiIH0sDQorICB7IE5VTEwgLCBOVUxMIH0NCit9Ow0KKw0KK0dMT0JBTF9SRU1PVkVf
SUZfVU5SRUZFUkVOQ0VEDQorRUZJX1VOSUNPREVfU1RSSU5HX1RBQkxFIGdHdnRHb3BDb250cm9s
bGVyTmFtZVRhYmxlW10gPSB7DQorICB7ICJlbmc7ZW4iLCBMIkludGVsIEdWVC1nIFZpcnR1YWwg
R1BVIFBDSSBBZGFwdGVyIiB9LA0KKyAgeyBOVUxMICwgTlVMTCB9DQorfTsNCisNCitTVEFUSUMN
CitFRklfU1RBVFVTDQorRUZJQVBJDQorR3Z0R29wQmluZGluZ1N1cHBvcnRlZCAoDQorICBJTiBF
RklfRFJJVkVSX0JJTkRJTkdfUFJPVE9DT0wgKlRoaXMsDQorICBJTiBFRklfSEFORExFICAgICAg
ICAgICAgICAgICAgQ29udHJvbGxlckhhbmRsZSwNCisgIElOIEVGSV9ERVZJQ0VfUEFUSF9QUk9U
T0NPTCAgICAqUmVtYWluaW5nRGV2aWNlUGF0aCBPUFRJT05BTA0KKyAgKQ0KK3sNCisgIEVGSV9T
VEFUVVMgICAgICAgICAgU3RhdHVzOw0KKyAgRUZJX1BDSV9JT19QUk9UT0NPTCAqUGNpSW87DQor
DQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsICIlYTogPj4+XG4iLCBfX0ZVTkNUSU9OX18p
Ow0KKw0KKyAgU3RhdHVzID0gZ0JTLT5PcGVuUHJvdG9jb2wgKA0KKyAgICAgICAgICAgICAgICAg
IENvbnRyb2xsZXJIYW5kbGUsDQorICAgICAgICAgICAgICAgICAgJmdFZmlQY2lJb1Byb3RvY29s
R3VpZCwNCisgICAgICAgICAgICAgICAgICAoVk9JRCAqKikgJlBjaUlvLA0KKyAgICAgICAgICAg
ICAgICAgIFRoaXMtPkRyaXZlckJpbmRpbmdIYW5kbGUsDQorICAgICAgICAgICAgICAgICAgQ29u
dHJvbGxlckhhbmRsZSwNCisgICAgICAgICAgICAgICAgICBFRklfT1BFTl9QUk9UT0NPTF9CWV9E
UklWRVINCisgICAgICAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkg
ew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsDQorICAgICAgIk9wZW5Qcm90b2NvbCBn
RWZpUGNpSW9Qcm90b2NvbEd1aWQgZmFpbGVkIHdpdGggJWRcbiIsIFN0YXR1cw0KKyAgICAgICk7
DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIFN0YXR1cyA9IEludGVsVmlydHVhbEdwdUFj
dGl2ZSAoUGNpSW8pOw0KKw0KKyAgZ0JTLT5DbG9zZVByb3RvY29sICgNCisgICAgICAgIENvbnRy
b2xsZXJIYW5kbGUsDQorICAgICAgICAmZ0VmaVBjaUlvUHJvdG9jb2xHdWlkLA0KKyAgICAgICAg
VGhpcy0+RHJpdmVyQmluZGluZ0hhbmRsZSwNCisgICAgICAgIENvbnRyb2xsZXJIYW5kbGUNCisg
ICAgICAgICk7DQorDQorRG9uZToNCisgIEdWVF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA8
PDxcbiIsIF9fRlVOQ1RJT05fXyk7DQorICByZXR1cm4gU3RhdHVzOw0KK30NCisNCisNCitTVEFU
SUMNCitFRklfU1RBVFVTDQorRUZJQVBJDQorR3Z0R29wQmluZGluZ1N0YXJ0ICgNCisgIElOIEVG
SV9EUklWRVJfQklORElOR19QUk9UT0NPTCAqVGhpcywNCisgIElOIEVGSV9IQU5ETEUgICAgICAg
ICAgICAgICAgICBDb250cm9sbGVySGFuZGxlLA0KKyAgSU4gRUZJX0RFVklDRV9QQVRIX1BST1RP
Q09MICAgICpSZW1haW5pbmdEZXZpY2VQYXRoIE9QVElPTkFMDQorICApDQorew0KKyAgRUZJX1NU
QVRVUyAgICAgICAgICAgICAgIFN0YXR1czsNCisgIEVGSV9UUEwgICAgICAgICAgICAgICAgICBP
cmlnaW5hbFRQTDsNCisgIEdWVF9HT1BfUFJJVkFURV9EQVRBICAgICAqR3Z0R29wUHJpdmF0ZSA9
IE5VTEw7DQorICBVSU5UNjQgICAgICAgICAgICAgICAgICAgUGNpQXR0cjsNCisgIEVGSV9ERVZJ
Q0VfUEFUSF9QUk9UT0NPTCAqUGFyZW50RGV2aWNlUGF0aDsNCisgIEFDUElfQURSX0RFVklDRV9Q
QVRIICAgICBBY3BpRGV2aWNlTm9kZTsNCisgIEVGSV9QQ0lfSU9fUFJPVE9DT0wgICAgICAqQ2hp
bGRQY2lJbzsNCisNCisgIEdWVF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA+Pj5cbiIsIF9f
RlVOQ1RJT05fXyk7DQorDQorICBPcmlnaW5hbFRQTCA9IGdCUy0+UmFpc2VUUEwgKFRQTF9DQUxM
QkFDSyk7DQorDQorICBTdGF0dXMgPSBnQlMtPkFsbG9jYXRlUG9vbCAoDQorICAgICAgICAgICAg
ICAgICAgRWZpQm9vdFNlcnZpY2VzRGF0YSwNCisgICAgICAgICAgICAgICAgICBzaXplb2YoR1ZU
X0dPUF9QUklWQVRFX0RBVEEpLA0KKyAgICAgICAgICAgICAgICAgIChWT0lEICoqKSZHdnRHb3BQ
cml2YXRlDQorICAgICAgICAgICAgICAgICAgKTsNCisgIGlmIChFRklfRVJST1IgKFN0YXR1cykg
fHwgR3Z0R29wUHJpdmF0ZSA9PSBOVUxMKSB7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1Is
DQorICAgICAgIkFsbG9jYXRlUG9vbCBmYWlsZWQgZm9yIEdWVF9HT1BfUFJJVkFURV9EQVRBLCBz
aXplICVkLCBzdGF0dXMgJWRcbiIsDQorICAgICAgc2l6ZW9mKEdWVF9HT1BfUFJJVkFURV9EQVRB
KSwgU3RhdHVzDQorICAgICAgKTsNCisgICAgU3RhdHVzID0gRUZJX09VVF9PRl9SRVNPVVJDRVM7
DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIFplcm9NZW0gKEd2dEdvcFByaXZhdGUsIHNp
emVvZihHVlRfR09QX1BSSVZBVEVfREFUQSkpOw0KKyAgR3Z0R29wUHJpdmF0ZS0+U2lnbmF0dXJl
ID0gR1ZUX0dPUF9NQUdJQzsNCisNCisgIFN0YXR1cyA9IGdCUy0+QWxsb2NhdGVQb29sICgNCisg
ICAgICAgICAgICAgICAgICBFZmlCb290U2VydmljZXNEYXRhLA0KKyAgICAgICAgICAgICAgICAg
IHNpemVvZihJTlRFTF9WSVJUVUFMX0dQVSksDQorICAgICAgICAgICAgICAgICAgJkd2dEdvcFBy
aXZhdGUtPlZpcnR1YWxHcHUNCisgICAgICAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9FUlJP
UiAoU3RhdHVzKSB8fCBHdnRHb3BQcml2YXRlLT5WaXJ0dWFsR3B1ID09IE5VTEwpIHsNCisgICAg
R1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiQWxsb2NhdGVQb29sIGZhaWxlZCBmb3Ig
SU5URUxfVklSVFVBTF9HUFUsIHNpemUgJWQsIHN0YXR1cyAlZFxuIiwNCisgICAgICBzaXplb2Yo
SU5URUxfVklSVFVBTF9HUFUpLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBTdGF0dXMgPSBFRklf
T1VUX09GX1JFU09VUkNFUzsNCisgICAgZ290byBGcmVlOw0KKyAgfQ0KKyAgWmVyb01lbSAoR3Z0
R29wUHJpdmF0ZS0+VmlydHVhbEdwdSwgc2l6ZW9mKElOVEVMX1ZJUlRVQUxfR1BVKSk7DQorDQor
ICBTdGF0dXMgPSBnQlMtPk9wZW5Qcm90b2NvbCAoDQorICAgICAgICAgICAgICAgICAgQ29udHJv
bGxlckhhbmRsZSwNCisgICAgICAgICAgICAgICAgICAmZ0VmaVBjaUlvUHJvdG9jb2xHdWlkLA0K
KyAgICAgICAgICAgICAgICAgIChWT0lEICoqKSAmR3Z0R29wUHJpdmF0ZS0+UGNpSW8sDQorICAg
ICAgICAgICAgICAgICAgVGhpcy0+RHJpdmVyQmluZGluZ0hhbmRsZSwNCisgICAgICAgICAgICAg
ICAgICBDb250cm9sbGVySGFuZGxlLA0KKyAgICAgICAgICAgICAgICAgIEVGSV9PUEVOX1BST1RP
Q09MX0JZX0RSSVZFUg0KKyAgICAgICAgICAgICAgICAgICk7DQorICBpZiAoRUZJX0VSUk9SIChT
dGF0dXMpKSB7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgIkNhbid0IG9w
ZW4gcHJvdG9jb2wgZ0VmaVBjaUlvUHJvdG9jb2xHdWlkLCBzdGF0dXMgJWRcbiIsIFN0YXR1cw0K
KyAgICAgICk7DQorICAgIGdvdG8gRnJlZTsNCisgIH0NCisNCisgIFN0YXR1cyA9IEd2dEdvcFBy
aXZhdGUtPlBjaUlvLT5BdHRyaWJ1dGVzICgNCisgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIEd2dEdvcFByaXZhdGUtPlBjaUlvLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgRWZpUGNpSW9BdHRyaWJ1dGVPcGVyYXRpb25HZXQsDQorICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAwLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgJkd2dEdvcFByaXZhdGUtPk9yaWdpbmFsUGNpQXR0cg0KKyAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgKTsNCisgIGlmIChFRklfRVJST1IgKFN0YXR1cykpIHsNCisgICAgR1ZU
X0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiRmFpbGVkIEVmaVBjaUlvQXR0cmlidXRlT3Bl
cmF0aW9uR2V0LCBzdGF0dXMgJWRcbiIsIFN0YXR1cw0KKyAgICAgICk7DQorICAgIGdvdG8gRnJl
ZTsNCisgIH0NCisNCisgIFBjaUF0dHIgPSBFRklfUENJX0RFVklDRV9FTkFCTEU7DQorICBTdGF0
dXMgPSBHdnRHb3BQcml2YXRlLT5QY2lJby0+QXR0cmlidXRlcyAoDQorICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBHdnRHb3BQcml2YXRlLT5QY2lJbywNCisgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgIEVmaVBjaUlvQXR0cmlidXRlT3BlcmF0aW9uRW5hYmxlLA0K
KyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGNpQXR0ciwNCisgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgIE5VTEwpOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVz
KSkgew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9SLA0KKyAgICAgICJGYWlsZWQgRWZpUGNp
SW9BdHRyaWJ1dGVPcGVyYXRpb25FbmFibGUgJWxseCwgc3RhdHVzICVkXG4iLCBQY2lBdHRyLA0K
KyAgICAgIFN0YXR1cw0KKyAgICAgICk7DQorICAgIGdvdG8gRnJlZTsNCisgIH0NCisNCisgIFN0
YXR1cyA9IEludGVsVmlydHVhbEdwdUluaXQgKEd2dEdvcFByaXZhdGUpOw0KKyAgaWYgKEVGSV9F
UlJPUiAoU3RhdHVzKSkgew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9SLCAiRmFpbGVkIElu
dGVsVmlydHVhbEdwdUluaXQsIHN0YXR1cyAlZFxuIiwgU3RhdHVzKTsNCisgICAgZ290byBGcmVl
Ow0KKyAgfQ0KKw0KKyAgU3RhdHVzID0gZ0JTLT5IYW5kbGVQcm90b2NvbCAoDQorICAgICAgICAg
ICAgICAgICAgQ29udHJvbGxlckhhbmRsZSwNCisgICAgICAgICAgICAgICAgICAmZ0VmaURldmlj
ZVBhdGhQcm90b2NvbEd1aWQsDQorICAgICAgICAgICAgICAgICAgKFZPSUQgKiopICZQYXJlbnRE
ZXZpY2VQYXRoDQorICAgICAgICAgICAgICAgICAgKTsNCisgIGlmIChFRklfRVJST1IgKFN0YXR1
cykpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwgIkZhaWwgZ0VmaURldmljZVBhdGhQ
cm90b2NvbEd1aWQsIHN0YXR1cyAlZFxuIiwNCisgICAgICBTdGF0dXMNCisgICAgICApOw0KKyAg
ICBnb3RvIEZyZWU7DQorICB9DQorDQorICBaZXJvTWVtICgmQWNwaURldmljZU5vZGUsIHNpemVv
ZiAoQUNQSV9BRFJfREVWSUNFX1BBVEgpKTsNCisgIEFjcGlEZXZpY2VOb2RlLkhlYWRlci5UeXBl
ID0gQUNQSV9ERVZJQ0VfUEFUSDsNCisgIEFjcGlEZXZpY2VOb2RlLkhlYWRlci5TdWJUeXBlID0g
QUNQSV9BRFJfRFA7DQorICBBY3BpRGV2aWNlTm9kZS5BRFIgPSBBQ1BJX0RJU1BMQVlfQURSICgx
LCAwLCAwLCAxLCAwLCBBQ1BJX0FEUl9ESVNQTEFZX1RZUEVfRVhURVJOQUxfRElHSVRBTCwgMCwg
MCk7DQorICBTZXREZXZpY2VQYXRoTm9kZUxlbmd0aCAoJkFjcGlEZXZpY2VOb2RlLkhlYWRlciwg
c2l6ZW9mIChBQ1BJX0FEUl9ERVZJQ0VfUEFUSCkpOw0KKyAgR3Z0R29wUHJpdmF0ZS0+R29wRGV2
UGF0aCA9IEFwcGVuZERldmljZVBhdGhOb2RlICgNCisgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIFBhcmVudERldmljZVBhdGgsDQorICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAoRUZJX0RFVklDRV9QQVRIX1BST1RPQ09MICopICZBY3BpRGV2aWNlTm9kZQ0KKyAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgKTsNCisgIGlmIChHdnRHb3BQcml2YXRlLT5Hb3BEZXZQ
YXRoID09IE5VTEwpIHsNCisgICAgU3RhdHVzID0gRUZJX09VVF9PRl9SRVNPVVJDRVM7DQorICAg
IEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsICJGYWlsIEFwcGVuZERldmljZVBhdGhOb2RlLCBzdGF0
dXMgJWRcbiIsIFN0YXR1cyk7DQorICAgIGdvdG8gRnJlZTsNCisgIH0NCisNCisgIFN0YXR1cyA9
IGdCUy0+SW5zdGFsbE11bHRpcGxlUHJvdG9jb2xJbnRlcmZhY2VzICgNCisgICAgICAgICAgICAg
ICAgICAmR3Z0R29wUHJpdmF0ZS0+SGFuZGxlLA0KKyAgICAgICAgICAgICAgICAgICZnRWZpRGV2
aWNlUGF0aFByb3RvY29sR3VpZCwNCisgICAgICAgICAgICAgICAgICBHdnRHb3BQcml2YXRlLT5H
b3BEZXZQYXRoLA0KKyAgICAgICAgICAgICAgICAgIE5VTEwNCisgICAgICAgICAgICAgICAgICAp
Ow0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VS
Uk9SLA0KKyAgICAgICJDYW4ndCBpbnN0YWxsIHByb3RvY29sIGdFZmlEZXZpY2VQYXRoUHJvdG9j
b2xHdWlkLCBzdGF0dXMgJWRcbiIsDQorICAgICAgU3RhdHVzDQorICAgICAgKTsNCisgICAgZ290
byBGcmVlOw0KKyAgfQ0KKw0KKyAgU3RhdHVzID0gZ0JTLT5JbnN0YWxsTXVsdGlwbGVQcm90b2Nv
bEludGVyZmFjZXMgKA0KKyAgICAgICAgICAgICAgICAgICZHdnRHb3BQcml2YXRlLT5IYW5kbGUs
DQorICAgICAgICAgICAgICAgICAgJmdFZmlHcmFwaGljc091dHB1dFByb3RvY29sR3VpZCwNCisg
ICAgICAgICAgICAgICAgICAmR3Z0R29wUHJpdmF0ZS0+R3JhcGhpY3NPdXRwdXRQcm90b2NvbCwN
CisgICAgICAgICAgICAgICAgICBOVUxMDQorICAgICAgICAgICAgICAgICAgKTsNCisNCisgIGlm
IChFRklfRVJST1IgKFN0YXR1cykpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisg
ICAgICAiQ2FuJ3QgaW5zdGFsbCBwcm90b2NvbCBnRWZpR3JhcGhpY3NPdXRwdXRQcm90b2NvbEd1
aWQsIHN0YXR1cyAlZFxuIiwNCisgICAgICBTdGF0dXMNCisgICAgICApOw0KKyAgICBnb3RvIEZy
ZWU7DQorICB9DQorDQorICBTdGF0dXMgPSBnQlMtPk9wZW5Qcm90b2NvbCAoDQorICAgICAgICAg
ICAgICAgIENvbnRyb2xsZXJIYW5kbGUsDQorICAgICAgICAgICAgICAgICZnRWZpUGNpSW9Qcm90
b2NvbEd1aWQsDQorICAgICAgICAgICAgICAgIChWT0lEICoqKSAmQ2hpbGRQY2lJbywNCisgICAg
ICAgICAgICAgICAgVGhpcy0+RHJpdmVyQmluZGluZ0hhbmRsZSwNCisgICAgICAgICAgICAgICAg
R3Z0R29wUHJpdmF0ZS0+SGFuZGxlLA0KKyAgICAgICAgICAgICAgICBFRklfT1BFTl9QUk9UT0NP
TF9CWV9DSElMRF9DT05UUk9MTEVSDQorICAgICAgICAgICAgICAgICk7DQorICBpZiAoRUZJX0VS
Uk9SIChTdGF0dXMpKSB7DQorICAgIGdvdG8gRnJlZTsNCisgIH0NCisNCisgIGdvdG8gRG9uZTsN
CisNCitGcmVlOg0KKyAgaWYgKEd2dEdvcFByaXZhdGUtPlBjaUlvKSB7DQorICAgIGlmIChHdnRH
b3BQcml2YXRlLT5PcmlnaW5hbFBjaUF0dHIpIHsNCisgICAgICBHdnRHb3BQcml2YXRlLT5QY2lJ
by0+QXR0cmlidXRlcyAoDQorICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3Z0R29wUHJp
dmF0ZS0+UGNpSW8sDQorICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRWZpUGNpSW9BdHRy
aWJ1dGVPcGVyYXRpb25FbmFibGUsDQorICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3Z0
R29wUHJpdmF0ZS0+T3JpZ2luYWxQY2lBdHRyLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIE5VTEwNCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApOw0KKyAgICB9DQorICAg
IGdCUy0+Q2xvc2VQcm90b2NvbCAoDQorICAgICAgICAgICBDb250cm9sbGVySGFuZGxlLA0KKyAg
ICAgICAgICAgJmdFZmlQY2lJb1Byb3RvY29sR3VpZCwNCisgICAgICAgICAgIFRoaXMtPkRyaXZl
ckJpbmRpbmdIYW5kbGUsDQorICAgICAgICAgICBDb250cm9sbGVySGFuZGxlDQorICAgICAgICAg
ICApOw0KKyAgICBHdnRHb3BQcml2YXRlLT5QY2lJbyA9IE5VTEw7DQorICB9DQorDQorICBpZiAo
R3Z0R29wUHJpdmF0ZS0+VmlydHVhbEdwdSkgew0KKyAgICBnQlMtPkZyZWVQb29sIChHdnRHb3BQ
cml2YXRlLT5WaXJ0dWFsR3B1KTsNCisgICAgR3Z0R29wUHJpdmF0ZS0+VmlydHVhbEdwdSA9IE5V
TEw7DQorICB9DQorDQorICBpZiAoR3Z0R29wUHJpdmF0ZSkgew0KKyAgICBnQlMtPkZyZWVQb29s
IChHdnRHb3BQcml2YXRlKTsNCisgIH0NCisNCisgIGlmIChHdnRHb3BQcml2YXRlLT5Hb3BEZXZQ
YXRoKSB7DQorICAgIEZyZWVQb29sIChHdnRHb3BQcml2YXRlLT5Hb3BEZXZQYXRoKTsNCisgICAg
R3Z0R29wUHJpdmF0ZS0+R29wRGV2UGF0aCA9IE5VTEw7DQorICB9DQorDQorRG9uZToNCisNCisg
IGdCUy0+UmVzdG9yZVRQTCAoT3JpZ2luYWxUUEwpOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9W
RVJCT1NFLCAiJWE6IDw8PFxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIHJldHVybiBTdGF0dXM7
DQorfQ0KKw0KKw0KK1NUQVRJQw0KK0VGSV9TVEFUVVMNCitFRklBUEkNCitHdnRHb3BCaW5kaW5n
U3RvcCAoDQorICBJTiAgRUZJX0RSSVZFUl9CSU5ESU5HX1BST1RPQ09MICpUaGlzLA0KKyAgSU4g
IEVGSV9IQU5ETEUgICAgICAgICAgICAgICAgICBDb250cm9sbGVySGFuZGxlLA0KKyAgSU4gIFVJ
TlROICAgICAgICAgICAgICAgICAgICAgICBOdW1iZXJPZkNoaWxkcmVuLA0KKyAgSU4gIEVGSV9I
QU5ETEUgICAgICAgICAgICAgICAgICAqQ2hpbGRIYW5kbGVCdWZmZXIgT1BUSU9OQUwNCisgICkN
Cit7DQorICBFRklfR1JBUEhJQ1NfT1VUUFVUX1BST1RPQ09MICpHcmFwaGljc091dHB1dFByb3Rv
Y29sOw0KKyAgRUZJX1NUQVRVUyAgICAgICAgICAgICAgICAgICBTdGF0dXM7DQorICBHVlRfR09Q
X1BSSVZBVEVfREFUQSAgICAgICAgICpHdnRHb3BQcml2YXRlID0gTlVMTDsNCisNCisgIEdWVF9E
RUJVRyAoRUZJX0RfSU5GTywgIiVhOiA+Pj5cbiIsIF9fRlVOQ1RJT05fXyk7DQorDQorICBTdGF0
dXMgPSBnQlMtPk9wZW5Qcm90b2NvbCAoDQorICAgICAgICAgICAgICAgICAgQ29udHJvbGxlckhh
bmRsZSwNCisgICAgICAgICAgICAgICAgICAmZ0VmaUdyYXBoaWNzT3V0cHV0UHJvdG9jb2xHdWlk
LA0KKyAgICAgICAgICAgICAgICAgIChWT0lEICoqKSZHcmFwaGljc091dHB1dFByb3RvY29sLA0K
KyAgICAgICAgICAgICAgICAgIFRoaXMtPkRyaXZlckJpbmRpbmdIYW5kbGUsDQorICAgICAgICAg
ICAgICAgICAgQ29udHJvbGxlckhhbmRsZSwNCisgICAgICAgICAgICAgICAgICBFRklfT1BFTl9Q
Uk9UT0NPTF9HRVRfUFJPVE9DT0wNCisgICAgICAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9F
UlJPUiAoU3RhdHVzKSkgew0KKyAgICBTdGF0dXMgPSBFRklfTk9UX1NUQVJURUQ7DQorICAgIGdv
dG8gRG9uZTsNCisgIH0NCisNCisgIEd2dEdvcFByaXZhdGUgPSBHVlRfR09QX1BSSVZBVEVfREFU
QV9GUk9NX1RISVMgKEdyYXBoaWNzT3V0cHV0UHJvdG9jb2wpOw0KKyAgaWYgKCFHdnRHb3BQcml2
YXRlKSB7DQorICAgIFN0YXR1cyA9IEVGSV9OT1RfU1RBUlRFRDsNCisgICAgR1ZUX0RFQlVHIChF
RklfRF9FUlJPUiwNCisgICAgICAiSW50ZWwgR1ZULWcgR09QIGlzbid0IHN0YXJ0ZWQsIHN0YXR1
cyAlZFxuIiwgU3RhdHVzDQorICAgICAgKTsNCisgICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyAg
Z0JTLT5Vbmluc3RhbGxNdWx0aXBsZVByb3RvY29sSW50ZXJmYWNlcyAoDQorICAgICAgICAgR3Z0
R29wUHJpdmF0ZS0+SGFuZGxlLA0KKyAgICAgICAgICZnRWZpR3JhcGhpY3NPdXRwdXRQcm90b2Nv
bEd1aWQsDQorICAgICAgICAgJkd2dEdvcFByaXZhdGUtPkdyYXBoaWNzT3V0cHV0UHJvdG9jb2ws
DQorICAgICAgICAgTlVMTA0KKyAgICAgICAgICk7DQorDQorICBpZiAoR3Z0R29wUHJpdmF0ZS0+
UGNpSW8pIHsNCisgICAgZ0JTLT5DbG9zZVByb3RvY29sICgNCisgICAgICAgICAgIENvbnRyb2xs
ZXJIYW5kbGUsDQorICAgICAgICAgICAmZ0VmaVBjaUlvUHJvdG9jb2xHdWlkLA0KKyAgICAgICAg
ICAgVGhpcy0+RHJpdmVyQmluZGluZ0hhbmRsZSwNCisgICAgICAgICAgIENvbnRyb2xsZXJIYW5k
bGUNCisgICAgICAgICAgICk7DQorICAgIEd2dEdvcFByaXZhdGUtPlBjaUlvID0gTlVMTDsNCisg
IH0NCisNCisgIFN0YXR1cyA9IEludGVsVmlydHVhbEdwdUNsZWFuIChHdnRHb3BQcml2YXRlKTsN
CisgIGlmIChFRklfRVJST1IgKFN0YXR1cykpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJP
UiwgIkZhaWwgdG8gY2xlYW4gdmlydHVhbCBHUFUsIHN0YXR1cyAlZFxuIiwgU3RhdHVzKTsNCisg
ICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyAgaWYgKEd2dEdvcFByaXZhdGUtPlZpcnR1YWxHcHUp
IHsNCisgICAgZ0JTLT5GcmVlUG9vbCAoR3Z0R29wUHJpdmF0ZS0+VmlydHVhbEdwdSk7DQorICAg
IEd2dEdvcFByaXZhdGUtPlZpcnR1YWxHcHUgPSBOVUxMOw0KKyAgfQ0KKw0KKyAgaWYgKEd2dEdv
cFByaXZhdGUpIHsNCisgICAgZ0JTLT5GcmVlUG9vbCAoR3Z0R29wUHJpdmF0ZSk7DQorICB9DQor
DQorRG9uZToNCisNCisgIEdWVF9ERUJVRyAoRUZJX0RfSU5GTywgIiVhOiA8PDxcbiIsIF9fRlVO
Q1RJT05fXyk7DQorDQorICByZXR1cm4gU3RhdHVzOw0KK30NCisNCitTVEFUSUMgRUZJX0RSSVZF
Ul9CSU5ESU5HX1BST1RPQ09MIGdHdnRHb3BEcml2ZXJCaW5kaW5nID0gew0KKyAgR3Z0R29wQmlu
ZGluZ1N1cHBvcnRlZCwNCisgIEd2dEdvcEJpbmRpbmdTdGFydCwNCisgIEd2dEdvcEJpbmRpbmdT
dG9wLA0KKyAgMHgxMCwNCisgIE5VTEwsDQorICBOVUxMDQorfTsNCisNCitFRklfU1RBVFVTDQor
RUZJQVBJDQorR3Z0R29wQ29tcG9uZW50TmFtZUdldERyaXZlck5hbWUgKA0KKyAgSU4gIEVGSV9D
T01QT05FTlRfTkFNRV9QUk9UT0NPTCAgKlRoaXMsDQorICBJTiAgQ0hBUjggICAgICAgICAgICAg
ICAgICAgICAgICAqTGFuZ3VhZ2UsDQorICBPVVQgQ0hBUjE2ICAgICAgICAgICAgICAgICAgICAg
ICAqKkRyaXZlck5hbWUNCisgICkNCit7DQorICByZXR1cm4gTG9va3VwVW5pY29kZVN0cmluZzIg
KA0KKyAgICAgICAgICAgTGFuZ3VhZ2UsDQorICAgICAgICAgICBUaGlzLT5TdXBwb3J0ZWRMYW5n
dWFnZXMsDQorICAgICAgICAgICBnR3Z0R29wRHJpdmVyTmFtZVRhYmxlLA0KKyAgICAgICAgICAg
RHJpdmVyTmFtZSwNCisgICAgICAgICAgIChCT09MRUFOKShUaGlzID09ICZnR3Z0R29wRHJpdmVy
Q29tcG9uZW50TmFtZSkNCisgICAgICAgICAgICk7DQorfQ0KKw0KK0VGSV9TVEFUVVMNCitFRklB
UEkNCitHdnRHb3BDb21wb25lbnROYW1lR2V0Q29udHJvbGxlck5hbWUgKA0KKyAgSU4gIEVGSV9D
T01QT05FTlRfTkFNRV9QUk9UT0NPTCAqVGhpcywNCisgIElOICBFRklfSEFORExFICAgICAgICAg
ICAgICAgICAgQ29udHJvbGxlckhhbmRsZSwNCisgIElOICBFRklfSEFORExFICAgICAgICAgICAg
ICAgICAgQ2hpbGRIYW5kbGUgT1BUSU9OQUwsDQorICBJTiAgQ0hBUjggICAgICAgICAgICAgICAg
ICAgICAgICpMYW5ndWFnZSwNCisgIE9VVCBDSEFSMTYgICAgICAgICAgICAgICAgICAgICAgKipD
b250cm9sbGVyTmFtZQ0KKyAgKQ0KK3sNCisgIEVGSV9TVEFUVVMgU3RhdHVzOw0KKw0KKyAgaWYg
KENoaWxkSGFuZGxlICE9IE5VTEwpIHsNCisgICAgcmV0dXJuIEVGSV9VTlNVUFBPUlRFRDsNCisg
IH0NCisNCisgIFN0YXR1cyA9IEVmaVRlc3RNYW5hZ2VkRGV2aWNlICgNCisgICAgICAgICAgICAg
Q29udHJvbGxlckhhbmRsZSwNCisgICAgICAgICAgICAgZ0d2dEdvcERyaXZlckJpbmRpbmcuRHJp
dmVyQmluZGluZ0hhbmRsZSwNCisgICAgICAgICAgICAgJmdFZmlQY2lJb1Byb3RvY29sR3VpZA0K
KyAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICByZXR1
cm4gU3RhdHVzOw0KKyAgfQ0KKw0KKyAgcmV0dXJuIExvb2t1cFVuaWNvZGVTdHJpbmcyICgNCisg
ICAgICAgICAgIExhbmd1YWdlLA0KKyAgICAgICAgICAgVGhpcy0+U3VwcG9ydGVkTGFuZ3VhZ2Vz
LA0KKyAgICAgICAgICAgZ0d2dEdvcENvbnRyb2xsZXJOYW1lVGFibGUsDQorICAgICAgICAgICBD
b250cm9sbGVyTmFtZSwNCisgICAgICAgICAgIChCT09MRUFOKShUaGlzID09ICZnR3Z0R29wRHJp
dmVyQ29tcG9uZW50TmFtZSkNCisgICAgICAgICAgICk7DQorfQ0KKw0KK0VGSV9TVEFUVVMNCitF
RklBUEkNCitHdnRHb3BFbnRyeVBvaW50ICgNCisgIElOIEVGSV9IQU5ETEUgICAgICAgSW1hZ2VI
YW5kbGUsDQorICBJTiBFRklfU1lTVEVNX1RBQkxFICpTeXN0ZW1UYWJsZQ0KKyAgKQ0KK3sNCisg
IEVGSV9TVEFUVVMgU3RhdHVzOw0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWE6
ID4+PlxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIFN0YXR1cyA9IEVmaUxpYkluc3RhbGxEcml2
ZXJCaW5kaW5nQ29tcG9uZW50TmFtZTIgKA0KKyAgICAgICAgICAgICBJbWFnZUhhbmRsZSwNCisg
ICAgICAgICAgICAgU3lzdGVtVGFibGUsDQorICAgICAgICAgICAgICZnR3Z0R29wRHJpdmVyQmlu
ZGluZywNCisgICAgICAgICAgICAgSW1hZ2VIYW5kbGUsDQorICAgICAgICAgICAgICZnR3Z0R29w
RHJpdmVyQ29tcG9uZW50TmFtZSwNCisgICAgICAgICAgICAgJmdHdnRHb3BEcml2ZXJDb21wb25l
bnROYW1lMik7DQorICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgIEdWVF9ERUJVRyAo
RUZJX0RfRVJST1IsICJGYWlsZWQgdG8gaW5zdGFsbCBkcml2ZXIgJWQgOiAlZFxuIiwgU3RhdHVz
KTsNCisgIH0NCisNCisgIEdWVF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA8PDxcbiIsIF9f
RlVOQ1RJT05fXyk7DQorDQorICByZXR1cm4gU3RhdHVzOw0KK30NCmRpZmYgLS1naXQgYS9Pdm1m
UGtnL0ludGVsR3Z0R29wRHhlL0dwdVJlZy5jIGIvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9HcHVS
ZWcuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjc3OGMwOWQ1MTk4
YwotLS0gL2Rldi9udWxsCisrKyBiL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvR3B1UmVnLmMKQEAg
LTAsMCArMSw5MSBAQAorLyoqIEBmaWxlDQorICBDb21wb25lbnQgbmFtZSBmb3IgdGhlIFFFTVUg
dmlkZW8gY29udHJvbGxlci4NCisNCisgIENvcHlyaWdodCAoYykgMjAyMSwgSW50ZWwgQ29ycG9y
YXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuPEJSPg0KKw0KKyAgU1BEWC1MaWNlbnNlLUlkZW50
aWZpZXI6IEJTRC0yLUNsYXVzZS1QYXRlbnQNCisNCisqKi8NCisNCisjaW5jbHVkZSAiR3B1UmVn
LmgiDQorDQorRUZJX1NUQVRVUw0KK1JlZ1JlYWQzMiAoDQorICBJTiAgR1ZUX0dPUF9QUklWQVRF
X0RBVEEgKlByaXZhdGUsDQorICBJTiAgVUlOVDMyIE9mZnNldCwNCisgIE9VVCBVSU5UMzIgKlZh
bHVlUHRyDQorICApDQorew0KKyAgRUZJX1NUQVRVUyBTdGF0dXMgPSBFRklfSU5WQUxJRF9QQVJB
TUVURVI7DQorDQorICBpZiAoT2Zmc2V0IDwgTU1JT19TSVpFICYmIFZhbHVlUHRyICE9IE5VTEwp
IHsNCisgICAgU3RhdHVzID0gUHJpdmF0ZS0+UGNpSW8tPk1lbS5SZWFkICgNCisgICAgICAgICAg
ICAgICAgICAgICAgICAgIFByaXZhdGUtPlBjaUlvLA0KKyAgICAgICAgICAgICAgICAgICAgICAg
ICAgRWZpUGNpSW9XaWR0aFVpbnQzMiwNCisgICAgICAgICAgICAgICAgICAgICAgICAgIFBDSV9C
QVJfSURYMCwNCisgICAgICAgICAgICAgICAgICAgICAgICAgIE9mZnNldCwNCisgICAgICAgICAg
ICAgICAgICAgICAgICAgIDEsDQorICAgICAgICAgICAgICAgICAgICAgICAgICBWYWx1ZVB0cg0K
KyAgICAgICAgICAgICAgICAgICAgICAgICAgKTsNCisgICAgaWYgKEVGSV9FUlJPUiAoU3RhdHVz
KSkgew0KKyAgICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsICIlYSByZWcgJXgsIHZhbHVlICV4
LCBzdGF0dXMgJWRcbiIsDQorICAgICAgICBfX0ZVTkNUSU9OX18sIE9mZnNldCwgKlZhbHVlUHRy
LCBTdGF0dXMNCisgICAgICAgICk7DQorICAgIH0gZWxzZSB7DQorICAgICAgU3RhdHVzID0gRUZJ
X1NVQ0NFU1M7DQorICAgICAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWEgcmVnICV4LCB2
YWx1ZSAleCwgc3RhdHVzICVkXG4iLA0KKyAgICAgICAgX19GVU5DVElPTl9fLCBPZmZzZXQsICpW
YWx1ZVB0ciwgU3RhdHVzDQorICAgICAgICApOw0KKyAgICB9DQorICB9IGVsc2Ugew0KKyAgICBT
dGF0dXMgPSBFRklfSU5WQUxJRF9QQVJBTUVURVI7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJS
T1IsDQorICAgICAgIiVhIGludmFsaWQgcmVnICV4IG9yIFZhbHVlUHRyICVwLCBzdGF0dXMgJWRc
biIsDQorICAgICAgX19GVU5DVElPTl9fLCBPZmZzZXQsIFZhbHVlUHRyLCBTdGF0dXMNCisgICAg
ICApOw0KKyAgICBnb3RvIERvbmU7DQorICB9DQorDQorRG9uZToNCisgIHJldHVybiBTdGF0dXM7
DQorfQ0KKw0KK0VGSV9TVEFUVVMNCitSZWdXcml0ZTMyICgNCisgIElOIEdWVF9HT1BfUFJJVkFU
RV9EQVRBICpQcml2YXRlLA0KKyAgSU4gVUlOVDMyIE9mZnNldCwNCisgIElOIFVJTlQzMiBWYWx1
ZQ0KKyAgKQ0KK3sNCisgIEVGSV9TVEFUVVMgU3RhdHVzID0gRUZJX0lOVkFMSURfUEFSQU1FVEVS
Ow0KKw0KKyAgaWYgKE9mZnNldCA8IE1NSU9fU0laRSkgew0KKyAgICBTdGF0dXMgPSBQcml2YXRl
LT5QY2lJby0+TWVtLldyaXRlICgNCisgICAgICAgICAgICAgICAgICAgICAgICAgIFByaXZhdGUt
PlBjaUlvLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgRWZpUGNpSW9XaWR0aFVpbnQzMiwN
CisgICAgICAgICAgICAgICAgICAgICAgICAgIFBDSV9CQVJfSURYMCwNCisgICAgICAgICAgICAg
ICAgICAgICAgICAgIE9mZnNldCwNCisgICAgICAgICAgICAgICAgICAgICAgICAgIDEsDQorICAg
ICAgICAgICAgICAgICAgICAgICAgICAmVmFsdWUNCisgICAgICAgICAgICAgICAgICAgICAgICAg
ICk7DQorICAgIGlmIChFRklfRVJST1IgKFN0YXR1cykpIHsNCisgICAgICBHVlRfREVCVUcgKEVG
SV9EX0VSUk9SLCAiJWEgcmVnICV4LCB2YWx1ZSAleCwgc3RhdHVzICVkXG4iLA0KKyAgICAgICAg
X19GVU5DVElPTl9fLCBPZmZzZXQsIFZhbHVlLCBTdGF0dXMNCisgICAgICAgICk7DQorICAgIH0g
ZWxzZSB7DQorICAgICAgU3RhdHVzID0gRUZJX1NVQ0NFU1M7DQorICAgICAgR1ZUX0RFQlVHIChF
RklfRF9WRVJCT1NFLCAiJWEgcmVnICV4LCB2YWx1ZSAleCwgc3RhdHVzICVkXG4iLA0KKyAgICAg
ICAgX19GVU5DVElPTl9fLCBPZmZzZXQsIFZhbHVlLCBTdGF0dXMNCisgICAgICAgICk7DQorICAg
IH0NCisgIH0gZWxzZSB7DQorICAgIFN0YXR1cyA9IEVGSV9JTlZBTElEX1BBUkFNRVRFUjsNCisg
ICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwgIiVhIGludmFsaWQgcmVnICV4LCBzdGF0dXMgJWRc
biIsDQorICAgICAgX19GVU5DVElPTl9fLCBPZmZzZXQsIFN0YXR1cw0KKyAgICAgICk7DQorICAg
IGdvdG8gRG9uZTsNCisgIH0NCisNCitEb25lOg0KKyAgcmV0dXJuIFN0YXR1czsNCit9DQpkaWZm
IC0tZ2l0IGEvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9HcHVSZWcuaCBiL092bWZQa2cvSW50ZWxH
dnRHb3BEeGUvR3B1UmVnLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAw
Li5mNDZmNGNlZjljZDQKLS0tIC9kZXYvbnVsbAorKysgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhl
L0dwdVJlZy5oCkBAIC0wLDAgKzEsMTc1IEBACisvKiogQGZpbGUNCisgIENvbXBvbmVudCBuYW1l
IGZvciB0aGUgUUVNVSB2aWRlbyBjb250cm9sbGVyLg0KKw0KKyAgQ29weXJpZ2h0IChjKSAyMDIx
LCBJbnRlbCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC48QlI+DQorDQorICBTUERY
LUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTItQ2xhdXNlLVBhdGVudA0KKw0KKyoqLw0KKw0KKyNp
Zm5kZWYgX19HUFVSRUdfSF8NCisjZGVmaW5lIF9fR1BVUkVHX0hfDQorDQorI2luY2x1ZGUgIkNv
bW1vbi5oIg0KKw0KKyNkZWZpbmUgTU1JT19TSVpFIDB4MjAwMDAwDQorDQorI2RlZmluZSBWR1Rf
UFZJTkZPX1BBR0UgMHg3ODAwMA0KKyNkZWZpbmUgVkdUX1BWSU5GT19TSVpFIDB4MTAwMA0KKw0K
KyNkZWZpbmUgVkdUX01BR0lDICAgICAgICAgMHg0Nzc2NTQ0Nzc2NTQ0Nzc2VUxMICAvKiAndkdU
dkdUdkcnICovDQorI2RlZmluZSBWR1RfVkVSU0lPTl9NQUpPUiAxDQorI2RlZmluZSBWR1RfVkVS
U0lPTl9NSU5PUiAwDQorDQorI2RlZmluZSBWR1RfRFJWX0RJU1BMQVlfTk9UX1JFQURZIDANCisj
ZGVmaW5lIFZHVF9EUlZfRElTUExBWV9SRUFEWSAgICAgMQ0KKw0KK3N0cnVjdCB2Z3RfaWYgew0K
KyAgVUlOVDY0IG1hZ2ljOyAgICAvKiBWR1RfTUFHSUMgKi8NCisgIFVJTlQxNiB2ZXJzaW9uX21h
am9yOw0KKyAgVUlOVDE2IHZlcnNpb25fbWlub3I7DQorICBVSU5UMzIgdmd0X2lkOyAgICAvKiBJ
RCBvZiB2R1QgaW5zdGFuY2UgKi8NCisgIFVJTlQzMiB2Z3RfY2FwczsgICAgLyogVkdUIGNhcGFi
aWxpdGllcyAqLw0KKyAgVUlOVDMyIHJzdjFbMTFdOyAgICAvKiBwYWQgdG8gb2Zmc2V0IDB4NDAg
Ki8NCisgIC8qDQorICAgKiAgRGF0YSBzdHJ1Y3R1cmUgdG8gZGVzY3JpYmUgdGhlIGJhbG9vbmlu
ZyBpbmZvIG9mIHJlc291cmNlcy4NCisgICAqICBFYWNoIFZNIGNhbiBvbmx5IGhhdmUgb25lIHBv
cnRpb24gb2YgY29udGludW91cyBhcmVhIGZvciBub3cuDQorICAgKiAgKE1heSBzdXBwb3J0IHNj
YXR0ZXJlZCByZXNvdXJjZSBpbiBmdXR1cmUpDQorICAgKiAgKHN0YXJ0aW5nIGZyb20gb2Zmc2V0
IDB4NDApDQorICAgKi8NCisgIHN0cnVjdCB7DQorICAgIC8qIEFwZXJ0dXJlIHJlZ2lzdGVyIGJh
bG9vbmluZyAqLw0KKyAgICBzdHJ1Y3Qgew0KKyAgICAgIFVJTlQzMiBiYXNlOw0KKyAgICAgIFVJ
TlQzMiBzaXplOw0KKyAgICB9IG1hcHBhYmxlX2dtYWRyOyAgLyogYXBlcnR1cmUgKi8NCisgICAg
LyogR01BRFIgcmVnaXN0ZXIgYmFsb29uaW5nICovDQorICAgIHN0cnVjdCB7DQorICAgICAgVUlO
VDMyIGJhc2U7DQorICAgICAgVUlOVDMyIHNpemU7DQorICAgIH0gbm9ubWFwcGFibGVfZ21hZHI7
ICAvKiBub24gYXBlcnR1cmUgKi8NCisgICAgLyogYWxsb3dlZCBmZW5jZSByZWdpc3RlcnMgKi8N
CisgICAgVUlOVDMyIGZlbmNlX251bTsNCisgICAgVUlOVDMyIHJzdjJbM107DQorICB9IGF2YWls
X3JzOyAgICAvKiBhdmFpbGFibGUvYXNzaWduZWQgcmVzb3VyY2UgKi8NCisgIFVJTlQzMiByc3Yz
WzB4MjAwIC0gMjRdOyAgLyogcGFkIHRvIGhhbGYgcGFnZSAqLw0KKyAgLyoNCisgICAqIFRoZSBi
b3R0b20gaGFsZiBwYWdlIGlzIGZvciByZXNwb25zZSBmcm9tIEdmeCBkcml2ZXIgdG8gaHlwZXJ2
aXNvci4NCisgICAqLw0KKyAgVUlOVDMyIHJzdjQ7DQorICBVSU5UMzIgZGlzcGxheV9yZWFkeTsg
IC8qIHJlYWR5IGZvciBkaXNwbGF5IG93bmVyIHN3aXRjaCAqLw0KKw0KKyAgVUlOVDMyIHJzdjVb
NF07DQorDQorICBVSU5UMzIgZzJ2X25vdGlmeTsNCisgIFVJTlQzMiByc3Y2WzVdOw0KKw0KKyAg
VUlOVDMyIGN1cnNvcl94X2hvdDsNCisgIFVJTlQzMiBjdXJzb3JfeV9ob3Q7DQorDQorICBzdHJ1
Y3Qgew0KKyAgICBVSU5UMzIgbG87DQorICAgIFVJTlQzMiBoaTsNCisgIH0gcGRwWzRdOw0KKw0K
KyAgVUlOVDMyIGV4ZWNsaXN0X2NvbnRleHRfZGVzY3JpcHRvcl9sbzsNCisgIFVJTlQzMiBleGVj
bGlzdF9jb250ZXh0X2Rlc2NyaXB0b3JfaGk7DQorDQorICBVSU5UMzIgIHJzdjdbMHgyMDAgLSAy
NF07ICAgIC8qIHBhZCB0byBvbmUgcGFnZSAqLw0KK30gUEFDS0VEOw0KKw0KKyNkZWZpbmUgdmd0
aWZfb2Zmc2V0KHgpIChPRkZTRVRfT0Yoc3RydWN0IHZndF9pZiwgeCkpDQorI2RlZmluZSB2Z3Rp
Zl9yZWcoeCkgKFZHVF9QVklORk9fUEFHRSArIHZndGlmX29mZnNldCh4KSkNCisNCit0eXBlZGVm
IGVudW0gX0dQVV9ESVNQTEFZX1BJUEUgew0KKyAgUElQRV9JTlZBTElEID0gLTEsDQorICBQSVBF
X0EgPSAwLA0KKyAgUElQRV9CLA0KKyAgUElQRV9DLA0KKyAgUElQRV9NQVggPSBQSVBFX0MNCit9
IEdQVV9ESVNQTEFZX1BJUEU7DQorDQordHlwZWRlZiBlbnVtIF9HUFVfRElTUExBWV9QTEFORSB7
DQorICBQTEFORV9QUklNQVJZID0gMCwNCisgIFBMQU5FX1NQUklURTAsDQorICBQTEFORV9TUFJJ
VEUxLA0KKyAgUExBTkVfTUFYLA0KK30gR1BVX0RJU1BMQVlfUExBTkU7DQorDQorI2RlZmluZSBf
VFJBTlNfSFRPVEFMX0EgMHg2MDAwMA0KKyNkZWZpbmUgX1RSQU5TX1ZUT1RBTF9BIDB4NjAwMEMN
CisjZGVmaW5lIF9UUkFOU19SRUdfT0ZGU0VUKHRyYW5zKSAodHJhbnMgKiAweDEwMDApDQorDQor
I2RlZmluZSBfUFNfV0lOX1BPU18xX0EgMHg2ODE3MA0KKyNkZWZpbmUgX1BTX1dJTl9TWl8xX0Eg
MHg2ODE3NA0KKyNkZWZpbmUgX1BTX0NUUkxfMV9BIDB4NjgxODANCisjZGVmaW5lIF9QU19SRUdf
T0ZGU0VUKHBpcGUsIGlkKSAocGlwZSAqIDB4ODAwICsgaWQgKiAweDEwMCkNCisjZGVmaW5lIFBT
X1dJTl9QT1MocGlwZSwgaWQpIChfUFNfV0lOX1BPU18xX0EgKyBfUFNfUkVHX09GRlNFVChwaXBl
LCBpZCkpDQorI2RlZmluZSBQU19XSU5fU1oocGlwZSwgaWQpIChfUFNfV0lOX1NaXzFfQSArIF9Q
U19SRUdfT0ZGU0VUKHBpcGUsIGlkKSkNCisjZGVmaW5lIFBTX0NUUkwocGlwZSwgaWQpIChfUFNf
Q1RSTF8xX0EgKyBfUFNfUkVHX09GRlNFVChwaXBlLCBpZCkpDQorI2RlZmluZSAgIFBTX0NUUkxf
U0NBTEVSX0VOICgxIDw8IDMxKQ0KKyNkZWZpbmUgICBQU19DVFJMX1NDQUxFUl9NT0RFX01BU0sg
KDB4MyA8PCAyOCkNCisjZGVmaW5lICAgUFNfQ1RSTF9TQ0FMRVJfTU9ERV9EWU4gICgwIDw8IDI4
KQ0KKyNkZWZpbmUgICBQU19DVFJMX1NDQUxFUl9NT0RFX0hRICAoMSA8PCAyOCkNCisjZGVmaW5l
ICAgUFNfQ1RSTF9TQ0FMRVJfQklORElOR19NQVNLICAoMHg3IDw8IDI1KQ0KKyNkZWZpbmUgICBQ
U19DVFJMX1NDQUxFUl9CSU5ESU5HX1BJUEUgICgwIDw8IDI1KQ0KKyNkZWZpbmUgICBQU19DVFJM
X1BMQU5FX1NFTChwbGFuZSkgKCgocGxhbmUpICsgMSkgPDwgMjUpDQorI2RlZmluZSAgIFBTX0NU
UkxfU0NBTEVSX0ZJTFRFUl9NQVNLICAgICAgICAgKDMgPDwgMjMpDQorI2RlZmluZSAgIFBTX0NU
UkxfU0NBTEVSX0ZJTFRFUl9NRURJVU0gICAgICAgKDAgPDwgMjMpDQorDQorI2RlZmluZSBQSVBF
X1JFR19PRkZTRVQocGlwZSkgKHBpcGUgKiAweDEwMDApDQorI2RlZmluZSBfUElQRV9DT05GX0Eg
MHg3MDAwOA0KKyNkZWZpbmUgICBQSVBFX0NPTkZfRU5BQkxFICgxIDw8IDMxKQ0KKyNkZWZpbmUg
X1BJUEVfU1JDU1pfQSAweDYwMDFDDQorI2RlZmluZSBQSVBFX0NPTkYocGlwZSkgKF9QSVBFX0NP
TkZfQSArIFBJUEVfUkVHX09GRlNFVChwaXBlKSkNCisjZGVmaW5lIFBJUEVTUkMocGlwZSkgKF9Q
SVBFX1NSQ1NaX0EgKyBQSVBFX1JFR19PRkZTRVQocGlwZSkpDQorDQorI2RlZmluZSBfUExBTkVf
Q1RMXzFfQSAweDcwMTgwDQorI2RlZmluZSAgIFBMQU5FX0NUTF9FTkFCTEUgKDEgPDwgMzEpDQor
I2RlZmluZSAgIFBMQU5FX0NUTF9QSVBFX0dBTU1BX0VOQUJMRSAoMSA8PCAzMCkNCisjZGVmaW5l
ICAgUExBTkVfQ1RMX0ZPUk1BVF9NQVNLICgweEYgPDwgMjQpDQorI2RlZmluZSAgIFBMQU5FX0NU
TF9GT1JNQVRfWFJHQl84ODg4ICgweDQgPDwgMjQpDQorI2RlZmluZSAgIFBMQU5FX0NUTF9QSVBF
X0NTQ19FTkFCTEUgKDEgPDwgMjMpDQorI2RlZmluZSAgIFBMQU5FX0NUTF9LRVlfRU5BQkxFX01B
U0sgKDB4MyA8PCAyMSkNCisjZGVmaW5lICAgUExBTkVfQ1RMX09SREVSX1JHQlggKDEgPDwgMjAp
DQorI2RlZmluZSAgIFBMQU5FX0NUTF9SRU5ERVJfREVDT01QUkVTU0lPTl9FTkFCTEUgKDEgPDwg
MTUpDQorI2RlZmluZSAgIFBMQU5FX0NUTF9QTEFORV9HQU1NQV9ESVNBQkxFICgxIDw8IDEzKQ0K
KyNkZWZpbmUgICBQTEFORV9DVExfVElMRURfTUFTSyAoMHg3IDw8IDEwKQ0KKyNkZWZpbmUgICBQ
TEFORV9DVExfVElMRURfTElORUFSICgwIDw8IDEwKQ0KKyNkZWZpbmUgICBQTEFORV9DVExfQVNZ
TkNfRkxJUCAoMSA8PCA5KQ0KKyNkZWZpbmUgICBQTEFORV9DVExfQUxQSEFfTUFTSyAoMHgzIDw8
IDQpDQorI2RlZmluZSAgIFBMQU5FX0NUTF9BTFBIQV9ESVNBQkxFICgwIDw8IDQpDQorI2RlZmlu
ZSAgIFBMQU5FX0NUTF9ST1RBVEVfTUFTSyAoMHgzIDw8IDApDQorI2RlZmluZSAgIFBMQU5FX0NU
TF9ST1RBVEVfMCAoMHgwIDw8IDApDQorDQorI2RlZmluZSBfUExBTkVfU1RSSURFXzFfQSAweDcw
MTg4DQorI2RlZmluZSAgIFBMQU5FX1NUUklERV9NQVNLIDB4MUZGDQorI2RlZmluZSBfUExBTkVf
UE9TXzFfQSAgMHg3MDE4Qw0KKyNkZWZpbmUgX1BMQU5FX1NJWkVfMV9BIDB4NzAxOTANCisjZGVm
aW5lIF9QTEFORV9TVVJGXzFfQSAweDcwMTlDDQorI2RlZmluZSBfUExBTkVfUkVHX09GRlNFVChw
aXBlLCBwbGFuZSkgKHBpcGUgKiAweDEwMDAgKyBwbGFuZSAqIDB4MTAwKQ0KKw0KKyNkZWZpbmUg
SFRPVEFMKHRyYW5zKSAoX1RSQU5TX0hUT1RBTF9BICsgX1RSQU5TX1JFR19PRkZTRVQodHJhbnMp
KQ0KKyNkZWZpbmUgVlRPVEFMKHRyYW5zKSAoX1RSQU5TX1ZUT1RBTF9BICsgX1RSQU5TX1JFR19P
RkZTRVQodHJhbnMpKQ0KKw0KKyNkZWZpbmUgUExBTkVfQ1RMKHBpcGUsIHBsYW5lKSAoX1BMQU5F
X0NUTF8xX0EgKyBfUExBTkVfUkVHX09GRlNFVChwaXBlLCBwbGFuZSkpDQorI2RlZmluZSBQTEFO
RV9TVFJJREUocGlwZSwgcGxhbmUpIChfUExBTkVfU1RSSURFXzFfQSArIF9QTEFORV9SRUdfT0ZG
U0VUKHBpcGUsIHBsYW5lKSkNCisjZGVmaW5lIFBMQU5FX1BPUyhwaXBlLCBwbGFuZSkgKF9QTEFO
RV9QT1NfMV9BICsgX1BMQU5FX1JFR19PRkZTRVQocGlwZSwgcGxhbmUpKQ0KKyNkZWZpbmUgUExB
TkVfU0laRShwaXBlLCBwbGFuZSkgKF9QTEFORV9TSVpFXzFfQSArIF9QTEFORV9SRUdfT0ZGU0VU
KHBpcGUsIHBsYW5lKSkNCisjZGVmaW5lIFBMQU5FX1NVUkYocGlwZSwgcGxhbmUpIChfUExBTkVf
U1VSRl8xX0EgKyBfUExBTkVfUkVHX09GRlNFVChwaXBlLCBwbGFuZSkpDQorDQorRUZJX1NUQVRV
Uw0KK1JlZ1JlYWQzMiAoDQorICBJTiAgR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlByaXZhdGUsDQor
ICBJTiAgVUlOVDMyIE9mZnNldCwNCisgIE9VVCBVSU5UMzIgKlZhbHVlUHRyDQorICApOw0KKw0K
K0VGSV9TVEFUVVMNCitSZWdXcml0ZTMyICgNCisgIElOIEdWVF9HT1BfUFJJVkFURV9EQVRBICpQ
cml2YXRlLA0KKyAgSU4gVUlOVDMyIE9mZnNldCwNCisgIElOIFVJTlQzMiBWYWx1ZQ0KKyAgKTsN
CisNCisjZW5kaWYgLy9fX0dQVVJFR19IXw0KZGlmZiAtLWdpdCBhL092bWZQa2cvSW50ZWxHdnRH
b3BEeGUvR3R0LmMgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL0d0dC5jCm5ldyBmaWxlIG1vZGUg
MTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uMTI3ODJlYjVhZmFhCi0tLSAvZGV2L251bGwKKysr
IGIvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9HdHQuYwpAQCAtMCwwICsxLDE2MiBAQAorLyoqIEBm
aWxlDQorICBDb21wb25lbnQgbmFtZSBmb3IgdGhlIFFFTVUgdmlkZW8gY29udHJvbGxlci4NCisN
CisgIENvcHlyaWdodCAoYykgMjAyMSwgSW50ZWwgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVz
ZXJ2ZWQuPEJSPg0KKw0KKyAgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEJTRC0yLUNsYXVzZS1Q
YXRlbnQNCisNCisqKi8NCisNCisjaW5jbHVkZSAiQ29tbW9uLmgiDQorI2luY2x1ZGUgIkd0dC5o
Ig0KKyNpbmNsdWRlICJWaXJ0dWFsR3B1LmgiDQorDQorRUZJX1NUQVRVUw0KK0dHVFRHZXRFbnRy
eSAoDQorICBJTiAgR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlByaXZhdGUsDQorICBJTiAgVUlOVDY0
IEluZGV4LA0KKyAgT1VUIEdUVF9QVEVfRU5UUlkgKkVudHJ5DQorICApDQorew0KKyAgRUZJX1NU
QVRVUyAgICAgICAgICBTdGF0dXMgPSBFRklfSU5WQUxJRF9QQVJBTUVURVI7DQorICBFRklfUENJ
X0lPX1BST1RPQ09MICpQY2lJbzsNCisgIFBJTlRFTF9WSVJUVUFMX0dQVSAgVmlydHVhbEdwdTsN
CisNCisgIGlmIChFbnRyeSA9PSBOVUxMKSB7DQorICAgIFN0YXR1cyA9IEVGSV9JTlZBTElEX1BB
UkFNRVRFUjsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiJWEgaW52YWxp
ZCBHR1RUIGVudHJ5IHB0ciAlcCBhdCBJbmRleCAleCwgc3RhdHVzICVkXG4iLA0KKyAgICAgIF9f
RlVOQ1RJT05fXywgRW50cnksIEluZGV4LCBTdGF0dXMNCisgICAgICApOw0KKyAgICBnb3RvIERv
bmU7DQorICB9DQorDQorICBQY2lJbyA9IFByaXZhdGUtPlBjaUlvOw0KKyAgVmlydHVhbEdwdSA9
IChQSU5URUxfVklSVFVBTF9HUFUpUHJpdmF0ZS0+VmlydHVhbEdwdTsNCisNCisgIGlmIChJbmRl
eCA+PSBWaXJ0dWFsR3B1LT5WaXNpYmxlR0dUVE9mZnNldCAmJg0KKyAgICAgICBJbmRleCA8IFZp
cnR1YWxHcHUtPlZpc2libGVHR1RUT2Zmc2V0ICsgVmlydHVhbEdwdS0+VmlzaWJsZUdHVFRTaXpl
KSB7DQorICAgIFN0YXR1cyA9IFBjaUlvLT5NZW0uUmVhZCAoDQorICAgICAgICAgICAgICAgICAg
ICAgICAgICBQY2lJbywNCisgICAgICAgICAgICAgICAgICAgICAgICAgIEVmaVBjaUlvV2lkdGhV
aW50NjQsDQorICAgICAgICAgICAgICAgICAgICAgICAgICBQQ0lfQkFSX0lEWDAsDQorICAgICAg
ICAgICAgICAgICAgICAgICAgICBHVFRfT0ZGU0VUICsgSW5kZXggKiBHVFRfRU5UUllfU0laRSwN
CisgICAgICAgICAgICAgICAgICAgICAgICAgIDEsDQorICAgICAgICAgICAgICAgICAgICAgICAg
ICBFbnRyeQ0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgKTsNCisgICAgaWYgKEVGSV9FUlJP
UiAoU3RhdHVzKSkgew0KKyAgICAgIEVudHJ5ID0gMDsNCisgICAgICBHVlRfREVCVUcgKEVGSV9E
X0VSUk9SLA0KKyAgICAgICAgIkZhaWxlZCB0byBHZXQgR0dUVCBFbnRyeSBpbmRleCAlbHgsIHN0
YXR1cyAlZFxuIiwgSW5kZXgsIFN0YXR1cw0KKyAgICAgICAgKTsNCisgICAgfQ0KKyAgfSBlbHNl
IGlmIChJbmRleCA+PSBWaXJ0dWFsR3B1LT5JbnZpc2libGVHR1RUT2Zmc2V0ICYmDQorICAgICAg
ICAgICAgIEluZGV4IDwgVmlydHVhbEdwdS0+SW52aXNpYmxlR0dUVE9mZnNldCArIFZpcnR1YWxH
cHUtPkludmlzaWJsZUdHVFRTaXplKSB7DQorICAgIFN0YXR1cyA9IEVGSV9VTlNVUFBPUlRFRDsN
CisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiU2tpcCBnZXQgR0dUVCBpbmRl
eCAlbHggZm9yIGludmlzaWJsZSBHTUFEUlxuIiwgSW5kZXgNCisgICAgICApOw0KKyAgfSBlbHNl
IHsNCisgICAgU3RhdHVzID0gRUZJX09VVF9PRl9SRVNPVVJDRVM7DQorICAgIEdWVF9ERUJVRyAo
RUZJX0RfRVJST1IsDQorICAgICAgIlNraXAgZ2V0IEdHVFQgaW5kZXggJWx4IG91dC1vZi1yYW5n
ZSwgYmFsbG9vbiB1bnN1cHBvcnRlZFxuIiwNCisgICAgICBJbmRleA0KKyAgICAgICk7DQorICB9
DQorDQorICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJPU0UsICJHZXQgR0dUVCBFbnRyeSAlbHggYXQg
aW5kZXggJWx4XG4iLCAqRW50cnksIEluZGV4KTsNCisNCitEb25lOg0KKw0KKyAgcmV0dXJuIFN0
YXR1czsNCit9DQorDQorRUZJX1NUQVRVUw0KK0dHVFRTZXRFbnRyeSAoDQorICBJTiBHVlRfR09Q
X1BSSVZBVEVfREFUQSAqUHJpdmF0ZSwNCisgIElOIFVJTlQ2NCBJbmRleCwNCisgIElOIEdUVF9Q
VEVfRU5UUlkgRW50cnkNCisgICkNCit7DQorICBFRklfU1RBVFVTICAgICAgICAgIFN0YXR1cyA9
IEVGSV9JTlZBTElEX1BBUkFNRVRFUjsNCisgIEVGSV9QQ0lfSU9fUFJPVE9DT0wgKlBjaUlvOw0K
KyAgUElOVEVMX1ZJUlRVQUxfR1BVICBWaXJ0dWFsR3B1Ow0KKw0KKyAgUGNpSW8gPSBQcml2YXRl
LT5QY2lJbzsNCisgIFZpcnR1YWxHcHUgPSAoUElOVEVMX1ZJUlRVQUxfR1BVKVByaXZhdGUtPlZp
cnR1YWxHcHU7DQorDQorICBpZiAoSW5kZXggPj0gVmlydHVhbEdwdS0+VmlzaWJsZUdHVFRPZmZz
ZXQgJiYNCisgICAgICBJbmRleCA8IFZpcnR1YWxHcHUtPlZpc2libGVHR1RUT2Zmc2V0ICsgVmly
dHVhbEdwdS0+VmlzaWJsZUdHVFRTaXplKSB7DQorICAgIFN0YXR1cyA9IFBjaUlvLT5NZW0uV3Jp
dGUgKA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgUGNpSW8sDQorICAgICAgICAgICAgICAg
ICAgICAgICAgICBFZmlQY2lJb1dpZHRoVWludDY0LA0KKyAgICAgICAgICAgICAgICAgICAgICAg
ICAgUENJX0JBUl9JRFgwLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgR1RUX09GRlNFVCAr
IEluZGV4ICogR1RUX0VOVFJZX1NJWkUsDQorICAgICAgICAgICAgICAgICAgICAgICAgICAxLA0K
KyAgICAgICAgICAgICAgICAgICAgICAgICAgJkVudHJ5DQorICAgICAgICAgICAgICAgICAgICAg
ICAgICApOw0KKyAgICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgICAgR1ZUX0RFQlVH
IChFRklfRF9FUlJPUiwNCisgICAgICAgICJGYWlsZWQgdG8gU2V0IEdHVFQgRW50cnkgJWx4IGF0
IGluZGV4ICVseCwgc3RhdHVzICVkXG4iLA0KKyAgICAgICAgRW50cnksIEluZGV4LCBTdGF0dXMN
CisgICAgICAgICk7DQorICAgIH0NCisgIH0gZWxzZSBpZiAoSW5kZXggPj0gVmlydHVhbEdwdS0+
SW52aXNpYmxlR0dUVE9mZnNldCAmJg0KKyAgICAgICAgICAgICBJbmRleCA8IFZpcnR1YWxHcHUt
PkludmlzaWJsZUdHVFRPZmZzZXQgKyBWaXJ0dWFsR3B1LT5JbnZpc2libGVHR1RUU2l6ZSkgew0K
KyAgICBTdGF0dXMgPSBFRklfVU5TVVBQT1JURUQ7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJS
T1IsDQorICAgICAgIlNraXAgc2V0IEdHVFQgaW5kZXggJWx4IGZvciBpbnZpc2libGUgR01BRFJc
biIsIEluZGV4DQorICAgICAgKTsNCisgIH0gZWxzZSB7DQorICAgIFN0YXR1cyA9IEVGSV9PVVRf
T0ZfUkVTT1VSQ0VTOw0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9SLA0KKyAgICAgICJTa2lw
IHNldCBHR1RUIGluZGV4ICVseCBvdXQtb2YtcmFuZ2UsIGJhbGxvb24gdW5zdXBwb3J0ZWRcbiIs
IEluZGV4DQorICAgICAgKTsNCisgIH0NCisNCisgIEdWVF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwg
IlNldCBHR1RUIEVudHJ5ICVseCBhdCBpbmRleCAlbHhcbiIsIEVudHJ5LCBJbmRleCk7DQorDQor
ICByZXR1cm4gU3RhdHVzOw0KK30NCisNCitFRklfU1RBVFVTDQorVXBkYXRlR0dUVCAoDQorICBJ
TiBHVlRfR09QX1BSSVZBVEVfREFUQSAqUHJpdmF0ZSwNCisgIElOIEVGSV9QSFlTSUNBTF9BRERS
RVNTIEdNQWRkciwNCisgIElOIEVGSV9QSFlTSUNBTF9BRERSRVNTIFN5c0FkZHIsDQorICBJTiBV
SU5UTiAgICAgICAgICAgICAgICBQYWdlcw0KKyAgKQ0KK3sNCisgIEVGSV9TVEFUVVMgICAgICAg
ICBTdGF0dXMgPSBFRklfSU5WQUxJRF9QQVJBTUVURVI7DQorICBQSU5URUxfVklSVFVBTF9HUFUg
VmlydHVhbEdwdTsNCisgIFVJTlROICAgICAgICAgICAgICBHdHRPZmZzZXQsIEluZGV4Ow0KKyAg
R1RUX1BURV9FTlRSWSAgICAgIEVudHJ5Ow0KKw0KKyAgaWYgKCFJU19BTElHTkVEKFN5c0FkZHIs
IEdUVF9QQUdFX1NJWkUpKSB7DQorICAgIFN0YXR1cyA9IEVGSV9JTlZBTElEX1BBUkFNRVRFUjsN
CisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiRmFpbGVkIHRvIHVwZGF0ZSBH
R1RUIEdNQURSICVseCwgU3lzQWRkciAlbHggaXNuJ3QgYWxpZ25lZCB0byAweCVseCwgc3RhdHVz
ICVkXG4iLA0KKyAgICAgIEdNQWRkciwgU3lzQWRkciwgR1RUX1BBR0VfU0laRSwgU3RhdHVzDQor
ICAgICAgKTsNCisgICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyAgVmlydHVhbEdwdSA9IChQSU5U
RUxfVklSVFVBTF9HUFUpUHJpdmF0ZS0+VmlydHVhbEdwdTsNCisgIEd0dE9mZnNldCA9IChHTUFk
ZHIgLSBWaXJ0dWFsR3B1LT5HcHVNZW1BZGRyKSA+PiBHVFRfUEFHRV9TSElGVDsNCisNCisgIEdW
VF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwNCisgICAgIlVwZGF0ZSBHR1RUIEdNQURSICVseCwgU3lz
QWRkciAlbHgsIFBhZ2VzIDB4JWx4XG4iLA0KKyAgICBHTUFkZHIsIFN5c0FkZHIsIFBhZ2VzDQor
ICAgICk7DQorICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBQYWdlczsgSW5kZXgrKykgew0KKyAg
ICBFbnRyeSA9IFN5c0FkZHIgKyBJbmRleCAqIEdUVF9QQUdFX1NJWkU7DQorICAgIEVudHJ5IHw9
IChHVFRfUEFHRV9QUkVTRU5UIHwgR1RUX1BBR0VfUkVBRF9XUklURSk7DQorICAgIEVudHJ5IHw9
IChHVFRfUEFHRV9QV1QgfCBHVFRfUEFHRV9QQ0QpOw0KKyAgICBHR1RUU2V0RW50cnkgKFByaXZh
dGUsIEd0dE9mZnNldCArIEluZGV4LCBFbnRyeSk7DQorICB9DQorDQorICBTdGF0dXMgPSBFRklf
U1VDQ0VTUzsNCisNCitEb25lOg0KKyAgcmV0dXJuIFN0YXR1czsNCit9DQpkaWZmIC0tZ2l0IGEv
T3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9HdHQuaCBiL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvR3R0
LmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5mYzkxYjdhODRhMGEK
LS0tIC9kZXYvbnVsbAorKysgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL0d0dC5oCkBAIC0wLDAg
KzEsNTEgQEAKKy8qKiBAZmlsZQ0KKyAgQ29tcG9uZW50IG5hbWUgZm9yIHRoZSBRRU1VIHZpZGVv
IGNvbnRyb2xsZXIuDQorDQorICBDb3B5cmlnaHQgKGMpIDIwMjEsIEludGVsIENvcnBvcmF0aW9u
LiBBbGwgcmlnaHRzIHJlc2VydmVkLjxCUj4NCisNCisgIFNQRFgtTGljZW5zZS1JZGVudGlmaWVy
OiBCU0QtMi1DbGF1c2UtUGF0ZW50DQorDQorKiovDQorDQorI2lmbmRlZiBfX0dUVF9IXw0KKyNk
ZWZpbmUgX19HVFRfSF8NCisNCisjaW5jbHVkZSAiQ29tbW9uLmgiDQorDQordHlwZWRlZiBVSU5U
NjQgR1RUX1BURV9FTlRSWTsNCisNCisjZGVmaW5lIEdUVF9PRkZTRVQgICAgICAgICAgMHg4MDAw
MDANCisjZGVmaW5lIEdUVF9TSVpFICAgICAgICAgICAgMHg4MDAwMDANCisjZGVmaW5lIEdUVF9F
TlRSWV9TSVpFICAgICAgc2l6ZW9mKEdUVF9QVEVfRU5UUlkpDQorI2RlZmluZSBHVFRfRU5UUllf
TlVNICAgICAgIChHVFRfU0laRSAvIEdUVF9FTlRSWV9TSVpFKQ0KKyNkZWZpbmUgR1RUX1BBR0Vf
U0hJRlQgICAgICAxMg0KKyNkZWZpbmUgR1RUX1BBR0VfU0laRSAgICAgICAoMVVMIDw8IEdUVF9Q
QUdFX1NISUZUKQ0KKyNkZWZpbmUgR1RUX1BBR0VfTUFTSyAgICAgICAofihHVFRfUEFHRV9TSVpF
LTEpKQ0KKyNkZWZpbmUgR1RUX1BBR0VfUFJFU0VOVCAgICAweDAxDQorI2RlZmluZSBHVFRfUEFH
RV9SRUFEX1dSSVRFIDB4MDINCisjZGVmaW5lIEdUVF9QQUdFX1BXVCAgICAgICAgMHgwOA0KKyNk
ZWZpbmUgR1RUX1BBR0VfUENEICAgICAgICAweDEwDQorDQorRUZJX1NUQVRVUw0KK0dHVFRHZXRF
bnRyeSAoDQorICBJTiAgR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlByaXZhdGUsDQorICBJTiAgVUlO
VDY0IEluZGV4LA0KKyAgT1VUIEdUVF9QVEVfRU5UUlkgKkVudHJ5DQorICApOw0KKw0KK0VGSV9T
VEFUVVMNCitHR1RUU2V0RW50cnkgKA0KKyAgSU4gR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlByaXZh
dGUsDQorICBJTiBVSU5UNjQgSW5kZXgsDQorICBJTiBHVFRfUFRFX0VOVFJZIEVudHJ5DQorICAp
Ow0KKw0KK0VGSV9TVEFUVVMNCitVcGRhdGVHR1RUICgNCisgIElOIEdWVF9HT1BfUFJJVkFURV9E
QVRBICpQcml2YXRlLA0KKyAgSU4gRUZJX1BIWVNJQ0FMX0FERFJFU1MgR01BZGRyLA0KKyAgSU4g
RUZJX1BIWVNJQ0FMX0FERFJFU1MgU3lzQWRkciwNCisgIElOIFVJTlROICAgICAgICAgICAgICAg
IFBhZ2VzDQorICApOw0KKw0KKyNlbmRpZiAvL19fR1RUX0hfDQpkaWZmIC0tZ2l0IGEvT3ZtZlBr
Zy9JbnRlbEd2dEdvcER4ZS9JbnRlbEd2dEdvcER4ZS5pbmYgYi9Pdm1mUGtnL0ludGVsR3Z0R29w
RHhlL0ludGVsR3Z0R29wRHhlLmluZgpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAw
MDAwMDAuLmM2ZTE3NTFlMWEyMgotLS0gL2Rldi9udWxsCisrKyBiL092bWZQa2cvSW50ZWxHdnRH
b3BEeGUvSW50ZWxHdnRHb3BEeGUuaW5mCkBAIC0wLDAgKzEsNTkgQEAKKyMjIEBmaWxlDQorIyBJ
bnRlbCBHVlQtZyBHcmFwaGljcyBPdXRwdXQgUHJvdG9jb2wgZHJpdmVyDQorIw0KKyMgQ29weXJp
Z2h0IChDKSAyMDIxIEludGVsIENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KKyMN
CisjIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMi1DbGF1c2UNCisjDQorIyMNCisNCitb
RGVmaW5lc10NCisgIElORl9WRVJTSU9OICAgICAgICAgICAgICAgICAgICA9IDB4MDAwMTAwMDUN
CisgIEJBU0VfTkFNRSAgICAgICAgICAgICAgICAgICAgICA9IEd2dEdvcER4ZQ0KKyAgRklMRV9H
VUlEICAgICAgICAgICAgICAgICAgICAgID0gN2MyYTBjMTQtMmE2My00ZDA4LTljN2YtZDU1Njkx
ZTFjZWRiDQorICBNT0RVTEVfVFlQRSAgICAgICAgICAgICAgICAgICAgPSBVRUZJX0RSSVZFUg0K
KyAgVkVSU0lPTl9TVFJJTkcgICAgICAgICAgICAgICAgID0gMi4wDQorICBFTlRSWV9QT0lOVCAg
ICAgICAgICAgICAgICAgICAgPSBHdnRHb3BFbnRyeVBvaW50DQorDQorW1NvdXJjZXNdDQorICBD
b21tb24uaA0KKyAgRGVidWdIZWxwZXIuaA0KKyAgRGlzcGxheS5jDQorICBEaXNwbGF5LmgNCisg
IEdvcERyaXZlci5jDQorICBHcHVSZWcuYw0KKyAgR3B1UmVnLmgNCisgIEd0dC5jDQorICBHdHQu
aA0KKyAgVmlydHVhbEdwdS5oDQorICBWaXJ0dWFsR3B1LmMNCisgIFZiZVNoaW0uYw0KKyAgVmJl
U2hpbS5oDQorDQorW1BhY2thZ2VzXQ0KKyAgTWRlUGtnL01kZVBrZy5kZWMNCisgIE1kZU1vZHVs
ZVBrZy9NZGVNb2R1bGVQa2cuZGVjDQorICBPdm1mUGtnL092bWZQa2cuZGVjDQorDQorW0xpYnJh
cnlDbGFzc2VzXQ0KKyAgQmFzZU1lbW9yeUxpYg0KKyAgRnJhbWVCdWZmZXJCbHRMaWINCisgIERl
YnVnTGliDQorICBEZXZpY2VQYXRoTGliDQorICBNZW1vcnlBbGxvY2F0aW9uTGliDQorICBQcmlu
dExpYg0KKyAgVWVmaUJvb3RTZXJ2aWNlc1RhYmxlTGliDQorICBVZWZpRHJpdmVyRW50cnlQb2lu
dA0KKyAgVWVmaUxpYg0KKyAgUGNkTGliDQorICBQY2lMaWINCisgIFFlbXVGd0NmZ0xpYg0KKw0K
K1tQcm90b2NvbHNdDQorICBnRWZpR3JhcGhpY3NPdXRwdXRQcm90b2NvbEd1aWQNCisgIGdFZmlQ
Y2lJb1Byb3RvY29sR3VpZA0KKyAgZ0VmaURldmljZVBhdGhQcm90b2NvbEd1aWQNCisNCitbUGNk
XQ0KKyAgZ0VmaU1kZU1vZHVsZVBrZ1Rva2VuU3BhY2VHdWlkLlBjZFZpZGVvSG9yaXpvbnRhbFJl
c29sdXRpb24NCisgIGdFZmlNZGVNb2R1bGVQa2dUb2tlblNwYWNlR3VpZC5QY2RWaWRlb1ZlcnRp
Y2FsUmVzb2x1dGlvbg0KZGlmZiAtLWdpdCBhL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmJlU2hp
bS5hc20gYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZiZVNoaW0uYXNtCm5ldyBmaWxlIG1vZGUg
MTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uNDNhNDQzNjJiNzk0Ci0tLSAvZGV2L251bGwKKysr
IGIvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9WYmVTaGltLmFzbQpAQCAtMCwwICsxLDM0MyBAQAor
Oy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KKzsgQGZpbGUNCis7IEEgbWluaW1hbCBJbnQxMGggc3R1
YiB0aGF0IGFsbG93cyB0aGUgV2luZG93cyAyMDA4IFIyIFNQMSBVRUZJIGd1ZXN0J3MgYnVnZ3ks
DQorOyBkZWZhdWx0IFZHQSBkcml2ZXIgdG8gc3dpdGNoIHRvIDEwMjR4NzY4eDMyLg0KKzsNCis7
IENvcHlyaWdodCAoYykgMjAyMSwgSW50ZWwgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2
ZWQuPEJSPg0KKzsgQ29weXJpZ2h0IChDKSAyMDIwLCBSZWJlY2NhIENyYW4gPHJlYmVjY2FAYnNk
aW8uY29tPg0KKzsgQ29weXJpZ2h0IChDKSAyMDE1LCBOYWhhbm5pIFN5c3RlbXMsIEluYy4NCis7
IENvcHlyaWdodCAoQykgMjAxNCwgUmVkIEhhdCwgSW5jLg0KKzsgQ29weXJpZ2h0IChjKSAyMDEz
IC0gMjAxNCwgSW50ZWwgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuPEJSPg0KKzsN
Cis7IFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMi1DbGF1c2UtUGF0ZW50DQorOw0KKzst
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0NCisNCis7IGVuYWJsZSB0aGlzIG1hY3JvIGZvciBkZWJ1ZyBt
ZXNzYWdlcw0KKyVkZWZpbmUgREVCVUcNCisNCislbWFjcm8gRGVidWdMb2cgMQ0KKyVpZmRlZiBE
RUJVRw0KKyAgcHVzaCAgICAgICBzaQ0KKyAgbW92ICAgICAgICBzaSwgJTENCisgIGNhbGwgICAg
ICAgUHJpbnRTdHJpbmdTaQ0KKyAgcG9wICAgICAgICBzaQ0KKyVlbmRpZg0KKyVlbmRtYWNybw0K
Kw0KKw0KK0JJVFMgMTYNCitPUkcgMA0KKw0KK1ZiZUluZm86DQorVElNRVMgMjU2IG5vcA0KKw0K
K1ZiZU1vZGVJbmZvOg0KK1ZiZU1vZGUxOg0KK1RJTUVTIDUwICBub3ANCitWYmVNb2RlMjoNCitU
SU1FUyA1MCAgbm9wDQorVmJlTW9kZTM6DQorVElNRVMgNTAgIG5vcA0KK1ZiZU1vZGU0Og0KK1RJ
TUVTIDUwICBub3ANCitUSU1FUyA1NiAgbm9wICA7IGZpbGxlciBmb3IgMjU2IGJ5dGVzDQorDQor
SGFuZGxlcjoNCisgIGNtcCAgICAgICAgYXgsIDB4NGYwMA0KKyAgamUgICAgICAgICBHZXRJbmZv
DQorICBjbXAgICAgICAgIGF4LCAweDRmMDENCisgIGplICAgICAgICAgR2V0TW9kZUluZm8NCisg
IGNtcCAgICAgICAgYXgsIDB4NGYwMg0KKyAgamUgICAgICAgICBTZXRNb2RlDQorICBjbXAgICAg
ICAgIGF4LCAweDRmMDMNCisgIGplICAgICAgICAgR2V0TW9kZQ0KKyAgY21wICAgICAgICBheCwg
MHg0ZjEwDQorICBqZSAgICAgICAgIEdldFBtQ2FwYWJpbGl0aWVzDQorICBjbXAgICAgICAgIGF4
LCAweDRmMTUNCisgIGplICAgICAgICAgUmVhZEVkaWQNCisgIGNtcCAgICAgICAgYWgsIDB4MDAN
CisgIGplICAgICAgICAgU2V0TW9kZUxlZ2FjeQ0KKyAgRGVidWdMb2cgICBTdHJVbmtvd25GdW5j
dGlvbg0KK0hhbmc6DQorICBqbXAgICAgICAgIEhhbmcNCisNCisNCitHZXRJbmZvOg0KKyAgcHVz
aCAgICAgICBlcw0KKyAgcHVzaCAgICAgICBkaQ0KKyAgcHVzaCAgICAgICBkcw0KKyAgcHVzaCAg
ICAgICBzaQ0KKyAgcHVzaCAgICAgICBjeA0KKw0KKyAgRGVidWdMb2cgICBTdHJFbnRlckdldElu
Zm8NCisNCisgIDsgdGFyZ2V0IChlczpkaSkgc2V0IG9uIGlucHV0DQorICBwdXNoICAgICAgIGNz
DQorICBwb3AgICAgICAgIGRzDQorICBtb3YgICAgICAgIHNpLCBWYmVJbmZvDQorICA7IHNvdXJj
ZSAoZHM6c2kpIHNldCBub3cNCisNCisgIG1vdiAgICAgICAgY3gsIDI1Ng0KKyAgY2xkDQorICBy
ZXAgbW92c2INCisNCisgIHBvcCAgICAgICAgY3gNCisgIHBvcCAgICAgICAgc2kNCisgIHBvcCAg
ICAgICAgZHMNCisgIHBvcCAgICAgICAgZGkNCisgIHBvcCAgICAgICAgZXMNCisgIGptcCAgICAg
ICAgU3VjY2Vzcw0KKw0KKw0KK0dldE1vZGVJbmZvOg0KKyAgcHVzaCAgICAgICBlcw0KKyAgcHVz
aCAgICAgICBkaQ0KKyAgcHVzaCAgICAgICBkcw0KKyAgcHVzaCAgICAgICBzaQ0KKyAgcHVzaCAg
ICAgICBjeA0KKw0KKyAgRGVidWdMb2cgICBTdHJFbnRlckdldE1vZGVJbmZvDQorDQorICBhbmQg
ICAgICAgIGN4LCB+MHg0MDAwIDsgY2xlYXIgcG90ZW50aWFsbHkgc2V0IExGQiBiaXQgaW4gbW9k
ZSBudW1iZXINCisNCisgIGNtcCAgICAgICAgY3gsIDB4MDEzZg0KKyAgamUgICAgICAgICBnS25v
d25Nb2RlMQ0KKyAgY21wICAgICAgICBjeCwgMHgwMTQwDQorICBqZSAgICAgICAgIGdLbm93bk1v
ZGUyDQorICBjbXAgICAgICAgIGN4LCAweDAxNDENCisgIGplICAgICAgICAgZ0tub3duTW9kZTMN
CisNCisgIERlYnVnTG9nICAgU3RyVW5rb3duTW9kZQ0KKyAgam1wICAgICAgICBIYW5nDQorZ0tu
b3duTW9kZTE6DQorICBEZWJ1Z0xvZyAgIFN0ck1vZGUxDQorICBtb3YgICAgICAgIHNpLCBWYmVN
b2RlMQ0KKyAgam1wICAgICAgICBDb3B5TW9kZUluZm8NCitnS25vd25Nb2RlMjoNCisgIERlYnVn
TG9nICAgU3RyTW9kZTINCisgIG1vdiAgICAgICAgc2ksIFZiZU1vZGUyDQorICBqbXAgICAgICAg
IENvcHlNb2RlSW5mbw0KK2dLbm93bk1vZGUzOg0KKyAgRGVidWdMb2cgICBTdHJNb2RlMw0KKyAg
bW92ICAgICAgICBzaSwgVmJlTW9kZTMNCisgIGptcCAgICAgICAgQ29weU1vZGVJbmZvDQorZ0tu
b3duTW9kZTQ6DQorICBEZWJ1Z0xvZyAgIFN0ck1vZGU0DQorICBtb3YgICAgICAgIHNpLCBWYmVN
b2RlNA0KKyAgam1wICAgICAgICBDb3B5TW9kZUluZm8NCisNCitDb3B5TW9kZUluZm86DQorICA7
IHRhcmdldCAoZXM6ZGkpIHNldCBvbiBpbnB1dA0KKyAgcHVzaCAgICAgICBjcw0KKyAgcG9wICAg
ICAgICBkcw0KKyAgO21vdiAgICAgICAgc2ksIFZiZU1vZGVJbmZvDQorICA7IHNvdXJjZSAoZHM6
c2kpIHNldCBub3cNCisNCisgIDttb3YgICAgICAgIGN4LCAyNTYNCisgIG1vdiAgICAgICAgY3gs
IDUwDQorICBjbGQNCisgIHJlcCBtb3ZzYg0KKw0KKyAgcG9wICAgICAgICBjeA0KKyAgcG9wICAg
ICAgICBzaQ0KKyAgcG9wICAgICAgICBkcw0KKyAgcG9wICAgICAgICBkaQ0KKyAgcG9wICAgICAg
ICBlcw0KKyAgam1wICAgICAgICBTdWNjZXNzDQorDQorDQorU2V0TW9kZToNCisgIHB1c2ggICAg
ICAgZHgNCisgIHB1c2ggICAgICAgYXgNCisNCisgIERlYnVnTG9nICAgU3RyRW50ZXJTZXRNb2Rl
DQorDQorICBhbmQgICAgICAgIGJ4LCB+MHg0MDAwIDsgY2xlYXIgcG90ZW50aWFsbHkgc2V0IExG
QiBiaXQgaW4gbW9kZSBudW1iZXINCisgIGNtcCAgICAgICAgYngsIDB4MDEzZg0KKyAgamUgICAg
ICAgICBLbm93bk1vZGUxDQorICBjbXAgICAgICAgIGJ4LCAweDAxNDANCisgIGplICAgICAgICAg
S25vd25Nb2RlMg0KKyAgY21wICAgICAgICBieCwgMHgwMTQxDQorICBqZSAgICAgICAgIEtub3du
TW9kZTMNCisgIERlYnVnTG9nICAgU3RyVW5rb3duTW9kZQ0KKyAgam1wICAgICAgICBIYW5nDQor
S25vd25Nb2RlMToNCisgIERlYnVnTG9nICAgU3RyTW9kZTENCisgIGptcCAgICAgICAgU2V0TW9k
ZURvbmUNCitLbm93bk1vZGUyOg0KKyAgRGVidWdMb2cgICBTdHJNb2RlMg0KKyAgam1wICAgICAg
ICBTZXRNb2RlRG9uZQ0KK0tub3duTW9kZTM6DQorICBEZWJ1Z0xvZyAgIFN0ck1vZGUzDQorICBq
bXAgICAgICAgIFNldE1vZGVEb25lDQorS25vd25Nb2RlNDoNCisgIERlYnVnTG9nICAgU3RyTW9k
ZTQNCisNCitTZXRNb2RlRG9uZToNCisgIG1vdiAgICAgICAgW0N1ck1vZGVdLCBibA0KKyAgbW92
ICAgICAgICBbQ3VyTW9kZSsxXSwgYmgNCisgIHBvcCAgICAgICAgYXgNCisgIHBvcCAgICAgICAg
ZHgNCisgIGptcCAgICAgICAgU3VjY2Vzcw0KKw0KKw0KK0dldE1vZGU6DQorICBEZWJ1Z0xvZyAg
IFN0ckVudGVyR2V0TW9kZQ0KKyAgbW92ICAgICAgICBibCwgW0N1ck1vZGVdDQorICBtb3YgICAg
ICAgIGJoLCBbQ3VyTW9kZSsxXQ0KKyAgam1wICAgICAgICBTdWNjZXNzDQorDQorDQorR2V0UG1D
YXBhYmlsaXRpZXM6DQorICBEZWJ1Z0xvZyAgIFN0ckdldFBtQ2FwYWJpbGl0aWVzDQorICBtb3Yg
ICAgICAgIGJ4LCAweDAwODANCisgIGptcCAgICAgICAgU3VjY2Vzcw0KKw0KKw0KK1JlYWRFZGlk
Og0KKyAgcHVzaCAgICAgICBlcw0KKyAgcHVzaCAgICAgICBkaQ0KKyAgcHVzaCAgICAgICBkcw0K
KyAgcHVzaCAgICAgICBzaQ0KKyAgcHVzaCAgICAgICBjeA0KKw0KKyAgRGVidWdMb2cgICBTdHJS
ZWFkRWRpZA0KKw0KKyAgOyB0YXJnZXQgKGVzOmRpKSBzZXQgb24gaW5wdXQNCisgIHB1c2ggICAg
ICAgY3MNCisgIHBvcCAgICAgICAgZHMNCisgIG1vdiAgICAgICAgc2ksIEVkaWQNCisgIDsgc291
cmNlIChkczpzaSkgc2V0IG5vdw0KKw0KKyAgbW92ICAgICAgICBjeCwgMTI4DQorICBjbGQNCisg
IHJlcCBtb3ZzYg0KKw0KKyAgcG9wICAgICAgICBjeA0KKyAgcG9wICAgICAgICBzaQ0KKyAgcG9w
ICAgICAgICBkcw0KKyAgcG9wICAgICAgICBkaQ0KKyAgcG9wICAgICAgICBlcw0KKyAgam1wICAg
ICAgICBTdWNjZXNzDQorDQorDQorU2V0TW9kZUxlZ2FjeToNCisgIERlYnVnTG9nICAgU3RyRW50
ZXJTZXRNb2RlTGVnYWN5DQorDQorICBjbXAgICAgICAgIGFsLCAweDAzDQorICBqZSAgICAgICAg
IHNLbm93bk1vZGUzDQorICBjbXAgICAgICAgIGFsLCAweDEyDQorICBqZSAgICAgICAgIHNLbm93
bk1vZGU0DQorICBEZWJ1Z0xvZyAgIFN0clVua293bk1vZGUNCisgIGptcCAgICAgICAgSGFuZw0K
K3NLbm93bk1vZGUzOg0KKyAgRGVidWdMb2cgICBTdHJMZWdhY3lNb2RlMw0KKyAgbW92ICAgICAg
ICBhbCwgMCA7IDB4MzANCisgIGptcCAgICAgICAgU2V0TW9kZUxlZ2FjeURvbmUNCitzS25vd25N
b2RlNDoNCisgIG1vdiAgICAgICAgYWwsIDAgOzB4MjANCitTZXRNb2RlTGVnYWN5RG9uZToNCisg
IERlYnVnTG9nICAgU3RyRXhpdFN1Y2Nlc3MNCisgIGlyZXQNCisNCisNCitTdWNjZXNzOg0KKyAg
RGVidWdMb2cgICBTdHJFeGl0U3VjY2Vzcw0KKyAgbW92ICAgICAgICBheCwgMHgwMDRmDQorICBp
cmV0DQorDQorDQorVW5zdXBwb3J0ZWQ6DQorICBEZWJ1Z0xvZyAgIFN0ckV4aXRVbnN1cHBvcnRl
ZA0KKyAgbW92ICAgICAgICBheCwgMHgwMjRmDQorICBpcmV0DQorDQorDQorJWlmZGVmIERFQlVH
DQorUHJpbnRTdHJpbmdTaToNCisgIHB1c2hhDQorICBwdXNoICAgICAgIGRzIDsgc2F2ZSBvcmln
aW5hbA0KKyAgcHVzaCAgICAgICBjcw0KKyAgcG9wICAgICAgICBkcw0KKyAgbW92ICAgICAgICBk
eCwgMHgyMjAgICAgICAgICAgICAgOyBiaHl2ZSBkZWJ1ZyBjb25zIHBvcnQNCisgIG1vdiAgICAg
ICAgYXgsIDANCitQcmludFN0cmluZ1NpTG9vcDoNCisgIGxvZHNiDQorICBjbXAgICAgICAgIGFs
LCAwDQorICBqZSAgICAgICAgIFByaW50U3RyaW5nU2lEb25lDQorICBvdXQgICAgICAgIGR4LCBh
bA0KKyAgam1wICAgICAgICBQcmludFN0cmluZ1NpTG9vcA0KK1ByaW50U3RyaW5nU2lEb25lOg0K
KyAgcG9wICAgICAgICBkcyA7IHJlc3RvcmUgb3JpZ2luYWwNCisgIHBvcGENCisgIHJldA0KKw0K
Kw0KK1N0ckV4aXRTdWNjZXNzOg0KKyAgZGIgJ3ZPaycsIDB4MGQsIDB4MGEsIDANCisNCitTdHJF
eGl0VW5zdXBwb3J0ZWQ6DQorICBkYiAndlVuc3VwcG9ydGVkJywgMHgwZCwgMHgwYSwgMA0KKw0K
K1N0clVua293bkZ1bmN0aW9uOg0KKyAgZGIgJ3ZVbmtub3duIEZ1bmN0aW9uJywgMHgwZCwgMHgw
YSwgMA0KKw0KK1N0ckVudGVyR2V0SW5mbzoNCisgIGRiICd2R2V0SW5mbycsIDB4MGQsIDB4MGEs
IDANCisNCitTdHJFbnRlckdldE1vZGVJbmZvOg0KKyAgZGIgJ3ZHZXRNb2RlSW5mbycsIDB4MGQs
IDB4MGEsIDANCisNCitTdHJFbnRlckdldE1vZGU6DQorICBkYiAndkdldE1vZGUnLCAweDBkLCAw
eDBhLCAwDQorDQorU3RyRW50ZXJTZXRNb2RlOg0KKyAgZGIgJ3ZTZXRNb2RlJywgMHgwZCwgMHgw
YSwgMA0KKw0KK1N0ckVudGVyU2V0TW9kZUxlZ2FjeToNCisgIGRiICd2U2V0TW9kZUxlZ2FjeScs
IDB4MGQsIDB4MGEsIDANCisNCitTdHJVbmtvd25Nb2RlOg0KKyAgZGIgJ3ZVbmtvd24gTW9kZScs
IDB4MGQsIDB4MGEsIDANCisNCitTdHJHZXRQbUNhcGFiaWxpdGllczoNCisgIGRiICd2R2V0UG1D
YXBhYmlsaXRpZXMnLCAweDBkLCAweDBhLCAwDQorDQorU3RyUmVhZEVkaWQ6DQorICBkYiAndlJl
YWRFZGlkJywgMHgwZCwgMHgwYSwgMA0KKw0KK1N0ckxlZ2FjeU1vZGUzOg0KKyAgZGIgJ3ZMZWdh
Y3lNb2RlMycsIDB4MGQsIDB4MGEsIDANCisNCisNCitTdHJNb2RlMToNCisgIGRiICdtb2RlXzY0
MHg0ODB4MzInLCAweDBkLCAweDBhLCAwDQorU3RyTW9kZTI6DQorICBkYiAnbW9kZV84MDB4NjAw
eDMyJywgMHgwZCwgMHgwYSwgMA0KK1N0ck1vZGUzOg0KKyAgZGIgJ21vZGVfMTAyNHg3Njh4MzIn
LCAweDBkLCAweDBhLCAwDQorU3RyTW9kZTQ6DQorICBkYiAnbW9kZV91bnVzZWQnLCAweDBkLCAw
eDBhLCAwDQorJWVuZGlmDQorDQorQ3VyTW9kZToNCisgIGRiIDB4MDAsIDB4MDANCisNCis7DQor
OyBFRElEIHN0b3JlcyBtb25pdG9yIGluZm9ybWF0aW9uLiBGb3Igbm93LCBqdXN0IHNlbmQgYmFj
ayBhbiBudWxsIGl0ZW0uDQorOw0KK0VkaWQ6DQorICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAw
LCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwDQorICBkYiAweDAwLCAweDAwLCAw
eDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwDQorICBkYiAweDAw
LCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwDQor
ICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAw
LCAweDAwDQorICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw
eDAwLCAweDAwLCAweDAwDQorICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAw
LCAweDAwLCAweDAwLCAweDAwLCAweDAwDQorICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw
eDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwDQorICBkYiAweDAwLCAweDAwLCAweDAw
LCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwDQorICBkYiAweDAwLCAw
eDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwDQorICBk
YiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw
eDAwDQorICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAw
LCAweDAwLCAweDAwDQorICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAw
eDAwLCAweDAwLCAweDAwLCAweDAwDQorICBkYiAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAw
LCAweDAwLCAweDAwLCAweDAwLCAweDAwLCAweDAwDQpkaWZmIC0tZ2l0IGEvT3ZtZlBrZy9JbnRl
bEd2dEdvcER4ZS9WYmVTaGltLmMgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZiZVNoaW0uYwpu
ZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLjgwNjMyMjRkNTNiNAotLS0g
L2Rldi9udWxsCisrKyBiL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmJlU2hpbS5jCkBAIC0wLDAg
KzEsMjU4IEBACisvKiogQGZpbGUNCisgIEluc3RhbGwgYSBmYWtlIFZHQUJJT1Mgc2VydmljZSBo
YW5kbGVyIChyZWFsIG1vZGUgSW50MTBoKSBmb3IgdGhlIGJ1Z2d5DQorICBXaW5kb3dzIDIwMDgg
UjIgU1AxIFVFRkkgZ3Vlc3QuDQorDQorICBUaGUgaGFuZGxlciBpcyBuZXZlciBtZWFudCB0byBi
ZSBkaXJlY3RseSBleGVjdXRlZCBieSBhIFZDUFU7IGl0J3MgdGhlcmUgZm9yDQorICB0aGUgaW50
ZXJuYWwgcmVhbCBtb2RlIGVtdWxhdG9yIG9mIFdpbmRvd3MgMjAwOCBSMiBTUDEuDQorDQorICBU
aGUgY29kZSBpcyBiYXNlZCBvbiBSYWxmIEJyb3duJ3MgSW50ZXJydXB0IExpc3Q6DQorICA8aHR0
cDovL3d3dy5jcy5jbXUuZWR1L35yYWxmL2ZpbGVzLmh0bWw+DQorICA8aHR0cDovL3d3dy5jdHlt
ZS5jb20vcmJyb3duLmh0bT4NCisNCisgIENvcHlyaWdodCAoYykgMjAyMSwgSW50ZWwgQ29ycG9y
YXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuPEJSPg0KKyAgQ29weXJpZ2h0IChDKSAyMDIwLCBS
ZWJlY2NhIENyYW4gPHJlYmVjY2FAYnNkaW8uY29tPg0KKyAgQ29weXJpZ2h0IChDKSAyMDE1LCBO
YWhhbm5pIFN5c3RlbXMsIEluYy4NCisgIENvcHlyaWdodCAoQykgMjAxNCwgUmVkIEhhdCwgSW5j
Lg0KKyAgQ29weXJpZ2h0IChjKSAyMDEzIC0gMjAxNCwgSW50ZWwgQ29ycG9yYXRpb24uIEFsbCBy
aWdodHMgcmVzZXJ2ZWQuPEJSPg0KKw0KKyAgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEJTRC0y
LUNsYXVzZS1QYXRlbnQNCisNCisqKi8NCisNCisjaW5jbHVkZSAiQ29tbW9uLmgiDQorI2luY2x1
ZGUgPEluZHVzdHJ5U3RhbmRhcmQvTGVnYWN5VmdhQmlvcy5oPg0KKyNpbmNsdWRlIDxMaWJyYXJ5
L1BjaUxpYi5oPg0KKyNpbmNsdWRlIDxMaWJyYXJ5L1ByaW50TGliLmg+DQorI2luY2x1ZGUgIlZi
ZVNoaW0uaCINCisNCisjcHJhZ21hIHBhY2sgKDEpDQordHlwZWRlZiBzdHJ1Y3Qgew0KKyAgVUlO
VDE2IE9mZnNldDsNCisgIFVJTlQxNiBTZWdtZW50Ow0KK30gSVZUX0VOVFJZOw0KKyNwcmFnbWEg
cGFjayAoKQ0KKw0KKy8vDQorLy8gVGhpcyBzdHJpbmcgaXMgZGlzcGxheWVkIGJ5IFdpbmRvd3Mg
MjAwOCBSMiBTUDEgaW4gdGhlIFNjcmVlbiBSZXNvbHV0aW9uLA0KKy8vIEFkdmFuY2VkIFNldHRp
bmdzIGRpYWxvZy4gSXQgc2hvdWxkIGJlIHNob3J0Lg0KKy8vDQorU1RBVElDIENPTlNUIENIQVI4
IG1Qcm9kdWN0UmV2aXNpb25bXSA9ICIyLjAiOw0KKw0KKyNkZWZpbmUgTlVNX1ZCRV9NT0RFUyAz
DQorU1RBVElDIENPTlNUIFVJTlQxNiB2YmVNb2RlSWRzW10gPSB7DQorICAweDEzZiwgIC8vIDY0
MHg0ODB4MzINCisgIDB4MTQwLCAgLy8gODAweDYwMHgzMg0KKyAgMHgxNDEgICAvLyAxMDI0eDc2
OHgzMg0KK307DQorDQorLy8gTW9kZXMgY2FuIGJlIHRvZ2dsZWQgd2l0aCBiaXQtMA0KKyNkZWZp
bmUgVkJFX01PREVfRU5BQkxFRCAgMHgwMEJCDQorI2RlZmluZSBWQkVfTU9ERV9ESVNBQkxFRCAw
eDAwQkENCisNCitTVEFUSUMgVkJFMl9NT0RFX0lORk8gdmJlTW9kZXNbXSA9IHsNCisgIHsgLy8g
MHgxM2YgNjQweDQ4MHgzMg0KKw0KKyAgICAvLyBNb2RlQXR0ciAtIEJ5dGVzUGVyU2NhbkxpbmUN
CisgICAgVkJFX01PREVfRElTQUJMRUQsIDB4MDcsIDB4MDAsIDB4NDAsIDB4NDAsIDB4QTAwMCwg
MHgwMCwgMHgwMDAwLCA2NDAqNCwNCisgICAgLy8gV2lkdGgsIEhlaWdodC4uLiwgVmJlMw0KKyAg
ICA2NDAsIDQ4MCwgMTYsIDgsIDEsIDMyLCAxLCAweDA2LCAwLCAwLCAxLA0KKyAgICAvLyBNYXNr
cw0KKyAgICAweDA4LCAweDEwLCAweDA4LCAweDA4LCAweDA4LCAweDAwLCAweDA4LCAweDE4LCAw
eDAwLA0KKyAgICAvLyBGcmFtZWJ1ZmZlcg0KKyAgICAweGRlYWRiZWVmLCAweDAwMDAsIDB4MDAw
MA0KKyAgfSwNCisgIHsgLy8gMHgxNDAgODAweDYwMHgzMg0KKw0KKyAgICAvLyBNb2RlQXR0ciAt
IEJ5dGVzUGVyU2NhbkxpbmUNCisgICAgVkJFX01PREVfRElTQUJMRUQsIDB4MDcsIDB4MDAsIDB4
NDAsIDB4NDAsIDB4QTAwMCwgMHgwMCwgMHgwMDAwLCA4MDAqNCwNCisgICAgLy8gV2lkdGgsIEhl
aWdodC4uLiwgVmJlMw0KKyAgICA4MDAsIDYwMCwgMTYsIDgsIDEsIDMyLCAxLCAweDA2LCAwLCAw
LCAxLA0KKyAgICAvLyBNYXNrcw0KKyAgICAweDA4LCAweDEwLCAweDA4LCAweDA4LCAweDA4LCAw
eDAwLCAweDA4LCAweDE4LCAweDAwLA0KKyAgICAvLyBGcmFtZWJ1ZmZlcg0KKyAgICAweGRlYWRi
ZWVmLCAweDAwMDAsIDB4MDAwMA0KKyAgfSwNCisgIHsgLy8gMHgxNDEgMTAyNHg3Njh4MzINCisN
CisgICAgLy8gTW9kZUF0dHIgLSBCeXRlc1BlclNjYW5MaW5lDQorICAgIFZCRV9NT0RFX0VOQUJM
RUQsIDB4MDcsIDB4MDAsIDB4NDAsIDB4NDAsIDB4QTAwMCwgMHgwMCwgMHgwMDAwLCAxMDI0KjQs
DQorICAgIC8vIFdpZHRoLCBIZWlnaHQuLi4sIFZiZTMNCisgICAgMTAyNCwgNzY4LCAxNiwgOCwg
MSwgMzIsIDEsIDB4MDYsIDAsIDAsIDEsDQorICAgIC8vIE1hc2tzDQorICAgIDB4MDgsIDB4MTAs
IDB4MDgsIDB4MDgsIDB4MDgsIDB4MDAsIDB4MDgsIDB4MTgsIDB4MDAsDQorICAgIC8vIEZyYW1l
YnVmZmVyDQorICAgIDB4ZGVhZGJlZWYsIDB4MDAwMCwgMHgwMDAwDQorICB9DQorfTsNCisNCisv
KioNCisgIEluc3RhbGwgdGhlIFZCRSBJbmZvIGFuZCBWQkUgTW9kZSBJbmZvIHN0cnVjdHVyZXMs
IGFuZCB0aGUgVkJFIHNlcnZpY2UNCisgIGhhbmRsZXIgcm91dGluZSBpbiB0aGUgQyBzZWdtZW50
LiBQb2ludCB0aGUgcmVhbC1tb2RlIEludDEwaCBpbnRlcnJ1cHQgdmVjdG9yDQorICB0byB0aGUg
aGFuZGxlci4gVGhlIG9ubHkgYWR2ZXJ0aXNlZCBtb2RlIGlzIDEwMjR4NzY4eDMyLg0KKw0KKyAg
QHBhcmFtW2luXSBDYXJkTmFtZSAgICAgICAgIE5hbWUgb2YgdGhlIHZpZGVvIGNhcmQgdG8gYmUg
ZXhwb3NlZCBpbiB0aGUNCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQcm9kdWN0IE5h
bWUgZmllbGQgb2YgdGhlIFZCRSBJbmZvIHN0cnVjdHVyZS4NCisgIEBwYXJhbVtpbl0gRnJhbWVC
dWZmZXJCYXNlICBHdWVzdC1waHlzaWNhbCBiYXNlIGFkZHJlc3Mgb2YgdGhlIHZpZGVvIGNhcmQn
cw0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1lIGJ1ZmZlci4NCisqKi8NCitW
T0lEDQorSW5zdGFsbFZiZVNoaW0gKA0KKyAgSU4gQ09OU1QgQ0hBUjE2ICAgICAgICAgKkNhcmRO
YW1lLA0KKyAgSU4gRUZJX1BIWVNJQ0FMX0FERFJFU1MgRnJhbWVCdWZmZXJCYXNlDQorICApDQor
ew0KKyAgRUZJX1BIWVNJQ0FMX0FERFJFU1MgU2VnbWVudDAsIFNlZ21lbnRDLCBTZWdtZW50RjsN
CisgIFVJTlROICAgICAgICAgICAgICAgIFNlZ21lbnQwUGFnZXM7DQorICBJVlRfRU5UUlkgICAg
ICAgICAgICAqSW50MHgxMDsNCisgIEVGSV9TVEFUVVMgICAgICAgICAgIFN0YXR1czsNCisgIFVJ
TlROICAgICAgICAgICAgICAgIFBhbTFBZGRyZXNzOw0KKyAgVUlOVDggICAgICAgICAgICAgICAg
UGFtMTsNCisgIFVJTlROICAgICAgICAgICAgICAgIFNlZ21lbnRDUGFnZXM7DQorICBWQkVfSU5G
TyAgICAgICAgICAgICAqVmJlSW5mb0Z1bGw7DQorICBWQkVfSU5GT19CQVNFICAgICAgICAqVmJl
SW5mbzsNCisgIFVJTlQ4ICAgICAgICAgICAgICAgICpQdHI7DQorICBVSU5UTiAgICAgICAgICAg
ICAgICBQcmludGVkOw0KKyAgVkJFX01PREVfSU5GTyAgICAgICAgKlZiZU1vZGVJbmZvOw0KKyAg
VUlOVE4gICAgICAgICAgICAgICAgaTsNCisNCisgIFNlZ21lbnQwID0gMHgwMDAwMDsNCisgIFNl
Z21lbnRDID0gMHhDMDAwMDsNCisgIFNlZ21lbnRGID0gMHhGMDAwMDsNCisNCisgIC8vDQorICAv
LyBBdHRlbXB0IHRvIGNvdmVyIHRoZSByZWFsIG1vZGUgSVZUIHdpdGggYW4gYWxsb2NhdGlvbi4g
VGhpcyBpcyBhIFVFRkkNCisgIC8vIGRyaXZlciwgaGVuY2UgdGhlIGFyY2ggcHJvdG9jb2xzIGhh
dmUgYmVlbiBpbnN0YWxsZWQgcHJldmlvdXNseS4gQW1vbmcNCisgIC8vIHRob3NlLCB0aGUgQ1BV
IGFyY2ggcHJvdG9jb2wgaGFzIGNvbmZpZ3VyZWQgdGhlIElEVCwgc28gd2UgY2FuIG92ZXJ3cml0
ZQ0KKyAgLy8gdGhlIElWVCB1c2VkIGluIHJlYWwgbW9kZS4NCisgIC8vDQorICAvLyBUaGUgYWxs
b2NhdGlvbiByZXF1ZXN0IG1heSBmYWlsLCBlZy4gaWYgTGVnYWN5Qmlvc0R4ZSBoYXMgYWxyZWFk
eSBydW4uDQorICAvLw0KKyAgU2VnbWVudDBQYWdlcyA9IDE7DQorICBJbnQweDEwICAgICAgID0g
KElWVF9FTlRSWSAqKShVSU5UTilTZWdtZW50MCArIDB4MTA7DQorICBTdGF0dXMgPSBnQlMtPkFs
bG9jYXRlUGFnZXMgKEFsbG9jYXRlQWRkcmVzcywgRWZpQm9vdFNlcnZpY2VzQ29kZSwNCisgICAg
ICAgICAgICAgICAgICBTZWdtZW50MFBhZ2VzLCAmU2VnbWVudDApOw0KKw0KKyAgaWYgKEVGSV9F
UlJPUiAoU3RhdHVzKSkgew0KKyAgICBFRklfUEhZU0lDQUxfQUREUkVTUyBIYW5kbGVyOw0KKw0K
KyAgICAvLw0KKyAgICAvLyBDaGVjayBpZiBhIHZpZGVvIEJJT1MgaGFuZGxlciBoYXMgYmVlbiBp
bnN0YWxsZWQgcHJldmlvdXNseSAtLSB3ZQ0KKyAgICAvLyBzaG91bGRuJ3Qgb3ZlcnJpZGUgYSBy
ZWFsIHZpZGVvIEJJT1Mgd2l0aCBvdXIgc2hpbSwgbm9yIG91ciBvd24gc2hpbSBpZg0KKyAgICAv
LyBpdCdzIGFscmVhZHkgcHJlc2VudC4NCisgICAgLy8NCisgICAgSGFuZGxlciA9IChJbnQweDEw
LT5TZWdtZW50IDw8IDQpICsgSW50MHgxMC0+T2Zmc2V0Ow0KKyAgICBpZiAoSGFuZGxlciA+PSBT
ZWdtZW50QyAmJiBIYW5kbGVyIDwgU2VnbWVudEYpIHsNCisgICAgICBERUJVRyAoKERFQlVHX1ZF
UkJPU0UsICIlYTogVmlkZW8gQklPUyBoYW5kbGVyIGZvdW5kIGF0ICUwNHg6JTA0eFxuIiwNCisg
ICAgICAgIF9fRlVOQ1RJT05fXywgSW50MHgxMC0+U2VnbWVudCwgSW50MHgxMC0+T2Zmc2V0KSk7
DQorICAgICAgcmV0dXJuOw0KKyAgICB9DQorDQorICAgIC8vDQorICAgIC8vIE90aGVyd2lzZSB3
ZSdsbCBvdmVyd3JpdGUgdGhlIEludDEwaCB2ZWN0b3IsIGV2ZW4gdGhvdWdoIHdlIG1heSBub3Qg
b3duDQorICAgIC8vIHRoZSBwYWdlIGF0IHplcm8uDQorICAgIC8vDQorICAgIERFQlVHICgoREVC
VUdfVkVSQk9TRSwgIiVhOiBmYWlsZWQgdG8gYWxsb2NhdGUgcGFnZSBhdCB6ZXJvOiAlclxuIiwN
CisgICAgICBfX0ZVTkNUSU9OX18sIFN0YXR1cykpOw0KKyAgfSBlbHNlIHsNCisgICAgLy8NCisg
ICAgLy8gV2UgbWFuYWdlZCB0byBhbGxvY2F0ZSB0aGUgcGFnZSBhdCB6ZXJvLiBTVk4gcjE0MjE4
IGd1YXJhbnRlZXMgdGhhdCBpdA0KKyAgICAvLyBpcyBOVUwtZmlsbGVkLg0KKyAgICAvLw0KKyAg
ICBBU1NFUlQgKEludDB4MTAtPlNlZ21lbnQgPT0gMHgwMDAwKTsNCisgICAgQVNTRVJUIChJbnQw
eDEwLT5PZmZzZXQgID09IDB4MDAwMCk7DQorICB9DQorDQorICAvLw0KKyAgLy8gUHV0IHRoZSBz
aGltIGluIHBsYWNlIGZpcnN0Lg0KKyAgLy8NCisgIFBhbTFBZGRyZXNzID0gUENJX0xJQl9BRERS
RVNTICgwLCAwLCAwLCAweDVBKTsNCisgIC8vDQorICAvLyBsb3cgbmliYmxlIGNvdmVycyAweEMw
MDAwIHRvIDB4QzNGRkYNCisgIC8vIGhpZ2ggbmliYmxlIGNvdmVycyAweEM0MDAwIHRvIDB4QzdG
RkYNCisgIC8vIGJpdDEgaW4gZWFjaCBuaWJibGUgaXMgV3JpdGUgRW5hYmxlDQorICAvLyBiaXQw
IGluIGVhY2ggbmliYmxlIGlzIFJlYWQgRW5hYmxlDQorICAvLw0KKyAgUGFtMSA9IFBjaVJlYWQ4
IChQYW0xQWRkcmVzcyk7DQorICBQY2lXcml0ZTggKFBhbTFBZGRyZXNzLCBQYW0xIHwgKEJJVDEg
fCBCSVQwKSk7DQorDQorICAvLw0KKyAgLy8gV2UgbmV2ZXIgYWRkZWQgbWVtb3J5IHNwYWNlIGR1
cmlnIFBFSSBvciBEWEUgZm9yIHRoZSBDIHNlZ21lbnQsIHNvIHdlDQorICAvLyBkb24ndCBuZWVk
IHRvIChhbmQgY2FuJ3QpIGFsbG9jYXRlIGZyb20gdGhlcmUuIEFsc28sIGd1ZXN0IG9wZXJhdGlu
Zw0KKyAgLy8gc3lzdGVtcyB3aWxsIHNlZSBhIGhvbGUgaW4gdGhlIFVFRkkgbWVtb3J5IG1hcCB0
aGVyZS4NCisgIC8vDQorICBTZWdtZW50Q1BhZ2VzID0gNDsNCisNCisgIEFTU0VSVCAoc2l6ZW9m
IGdWYmVTaGltIDw9IEVGSV9QQUdFU19UT19TSVpFIChTZWdtZW50Q1BhZ2VzKSk7DQorICBDb3B5
TWVtICgoVk9JRCAqKShVSU5UTilTZWdtZW50QywgZ1ZiZVNoaW0sIHNpemVvZiBnVmJlU2hpbSk7
DQorDQorICAvLw0KKyAgLy8gRmlsbCBpbiB0aGUgVkJFIElORk8gc3RydWN0dXJlLg0KKyAgLy8N
CisgIFZiZUluZm9GdWxsID0gKFZCRV9JTkZPICopKFVJTlROKVNlZ21lbnRDOw0KKyAgVmJlSW5m
byAgICAgPSAmVmJlSW5mb0Z1bGwtPkJhc2U7DQorICBQdHIgICAgICAgICA9IFZiZUluZm9GdWxs
LT5CdWZmZXI7DQorDQorICBDb3B5TWVtIChWYmVJbmZvLT5TaWduYXR1cmUsICJWRVNBIiwgNCk7
DQorICBWYmVJbmZvLT5WZXNhVmVyc2lvbiA9IDB4MDIwMDsNCisNCisgIFZiZUluZm8tPk9lbU5h
bWVBZGRyZXNzID0gKFVJTlQzMilTZWdtZW50QyA8PCAxMiB8IChVSU5UMTYpKChVSU5UTilQdHIt
U2VnbWVudEMpOw0KKyAgQ29weU1lbSAoUHRyLCAiRkJTRCIsIDUpOw0KKyAgUHRyICs9IDU7DQor
DQorICBWYmVJbmZvLT5DYXBhYmlsaXRpZXMgPSBCSVQxIHwgQklUMDsgLy8gREFDIGNhbiBiZSBz
d2l0Y2hlZCBpbnRvIDgtYml0IG1vZGUNCisNCisgIFZiZUluZm8tPk1vZGVMaXN0QWRkcmVzcyA9
IChVSU5UMzIpU2VnbWVudEMgPDwgMTIgfCAoVUlOVDE2KSgoVUlOVE4pUHRyLVNlZ21lbnRDKTsN
CisgIGZvciAoaSA9IDA7IGkgPCBOVU1fVkJFX01PREVTOyBpICsrKSB7DQorICAgICAqKFVJTlQx
NiopUHRyID0gdmJlTW9kZUlkc1tpXTsgIC8vIG1vZGUgbnVtYmVyDQorICAgICBQdHIgKz0gMjsN
CisgIH0NCisgICooVUlOVDE2KilQdHIgPSAweEZGRkY7IC8vIG1vZGUgbGlzdCB0ZXJtaW5hdG9y
DQorICBQdHIgKz0gMjsNCisNCisgIFZiZUluZm8tPlZpZGVvTWVtNjRLID0gKFVJTlQxNikoKDEw
MjQgKiA3NjggKiA0ICsgNjU1MzUpIC8gNjU1MzYpOw0KKyAgVmJlSW5mby0+T2VtU29mdHdhcmVW
ZXJzaW9uID0gMHgwMjAwOw0KKw0KKyAgVmJlSW5mby0+VmVuZG9yTmFtZUFkZHJlc3MgPSAoVUlO
VDMyKVNlZ21lbnRDIDw8IDEyIHwgKFVJTlQxNikoKFVJTlROKVB0ci1TZWdtZW50Qyk7DQorICBD
b3B5TWVtIChQdHIsICJGQlNEIiwgNSk7DQorICBQdHIgKz0gNTsNCisNCisgIFZiZUluZm8tPlBy
b2R1Y3ROYW1lQWRkcmVzcyA9IChVSU5UMzIpU2VnbWVudEMgPDwgMTIgfCAoVUlOVDE2KSgoVUlO
VE4pUHRyLVNlZ21lbnRDKTsNCisgIFByaW50ZWQgPSBBc2NpaVNQcmludCAoKENIQVI4ICopUHRy
LA0KKyAgICAgICAgICAgICAgc2l6ZW9mIFZiZUluZm9GdWxsLT5CdWZmZXIgLSAoUHRyIC0gVmJl
SW5mb0Z1bGwtPkJ1ZmZlciksICIlcyIsDQorICAgICAgICAgICAgICBDYXJkTmFtZSk7DQorICBQ
dHIgKz0gUHJpbnRlZCArIDE7DQorDQorICBWYmVJbmZvLT5Qcm9kdWN0UmV2QWRkcmVzcyA9IChV
SU5UMzIpU2VnbWVudEMgPDwgMTIgfCAoVUlOVDE2KSgoVUlOVE4pUHRyLVNlZ21lbnRDKTsNCisg
IENvcHlNZW0gKFB0ciwgbVByb2R1Y3RSZXZpc2lvbiwgc2l6ZW9mIG1Qcm9kdWN0UmV2aXNpb24p
Ow0KKyAgUHRyICs9IHNpemVvZiBtUHJvZHVjdFJldmlzaW9uOw0KKw0KKyAgQVNTRVJUIChzaXpl
b2YgVmJlSW5mb0Z1bGwtPkJ1ZmZlciA+PSBQdHIgLSBWYmVJbmZvRnVsbC0+QnVmZmVyKTsNCisg
IFplcm9NZW0gKFB0ciwgc2l6ZW9mIFZiZUluZm9GdWxsLT5CdWZmZXIgLSAoUHRyIC0gVmJlSW5m
b0Z1bGwtPkJ1ZmZlcikpOw0KKw0KKyAgLy8NCisgIC8vIEZpbGwgaW4gdGhlIFZCRSBNT0RFIElO
Rk8gc3RydWN0dXJlIGxpc3QNCisgIC8vDQorICBWYmVNb2RlSW5mbyA9IChWQkVfTU9ERV9JTkZP
ICopKFZiZUluZm9GdWxsICsgMSk7DQorICBQdHIgPSAoVUlOVDggKilWYmVNb2RlSW5mbzsNCisg
IGZvciAoaSA9IDA7IGkgPCBOVU1fVkJFX01PREVTOyBpKyspIHsNCisgICAgdmJlTW9kZXNbaV0u
TGZiQWRkcmVzcyA9IChVSU5UMzIpRnJhbWVCdWZmZXJCYXNlOw0KKyAgICBDb3B5TWVtIChQdHIs
ICZ2YmVNb2Rlc1tpXSwgMHgzMik7DQorICAgIFB0ciArPSAweDMyOw0KKyAgfQ0KKw0KKyAgWmVy
b01lbSAoUHRyLCA1Nik7ICAgICAvLyBDbGVhciByZW1haW5pbmcgYnl0ZXMNCisNCisgIC8vDQor
ICAvLyBDbGVhciBXcml0ZSBFbmFibGUgKGJpdDEpLCBrZWVwIFJlYWQgRW5hYmxlIChiaXQwKSBz
ZXQNCisgIC8vDQorICBQY2lXcml0ZTggKFBhbTFBZGRyZXNzLCAoUGFtMSAmIH5CSVQxKSB8IEJJ
VDApOw0KKw0KKyAgLy8NCisgIC8vIFNlY29uZCwgcG9pbnQgdGhlIEludDEwaCB2ZWN0b3IgYXQg
dGhlIHNoaW0uDQorICAvLw0KKyAgSW50MHgxMC0+U2VnbWVudCA9IChVSU5UMTYpICgoVUlOVDMy
KVNlZ21lbnRDID4+IDQpOw0KKyAgSW50MHgxMC0+T2Zmc2V0ICA9IChVSU5UMTYpICgoVUlOVE4p
IChWYmVNb2RlSW5mbyArIDEpIC0gU2VnbWVudEMpOw0KKw0KKyAgREVCVUcgKChERUJVR19JTkZP
LCAiJWE6IFZCRSBzaGltIGluc3RhbGxlZCB0byAleDoleFxuIiwNCisgICAgICAgICBfX0ZVTkNU
SU9OX18sIEludDB4MTAtPlNlZ21lbnQsIEludDB4MTAtPk9mZnNldCkpOw0KK30NCmRpZmYgLS1n
aXQgYS9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZiZVNoaW0uaCBiL092bWZQa2cvSW50ZWxHdnRH
b3BEeGUvVmJlU2hpbS5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4u
NjAxYjE0NjVjYmU1Ci0tLSAvZGV2L251bGwKKysrIGIvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9W
YmVTaGltLmgKQEAgLTAsMCArMSw5MTIgQEAKKy8vDQorLy8gVEhJUyBGSUxFIFdBUyBHRU5FUkFU
RUQgQlkgIlZiZVNoaW0uc2giLiBETyBOT1QgRURJVC4NCisvLw0KKyNpZm5kZWYgX1ZCRV9TSElN
X0hfDQorI2RlZmluZSBfVkJFX1NISU1fSF8NCitTVEFUSUMgQ09OU1QgVUlOVDggZ1ZiZVNoaW1b
XSA9IHsNCisgIC8qIDAwMDAwMDAwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDAxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDAyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDAzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDA0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDA1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDA2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDA3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDA4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDA5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDBBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDBCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDBDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDBEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDBFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDBGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDEwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDExIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDEyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDEzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDE0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDE1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDE2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDE3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDE4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDE5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDFBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDFCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDFDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDFEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDFFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDFGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDIwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDIxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDIyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDIzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDI0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDI1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDI2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDI3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDI4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDI5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDJBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDJCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDJDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDJEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDJFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDJGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDMwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDMxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDMyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDMzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDM0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDM1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDM2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDM3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDM4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDM5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDNBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDNCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDNDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDNEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDNFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDNGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQ0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQ1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQ2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQ3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQ4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDQ5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDRBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDRCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDRDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDREIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDRFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDRGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDUwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDUxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDUyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDUzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDU0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDU1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDU2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDU3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDU4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDU5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDVBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDVCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDVDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDVEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDVFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDVGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDYwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDYxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDYyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDYzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDY0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDY1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDY2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDY3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDY4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDY5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDZBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDZCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDZDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDZEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDZFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDZGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDcwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDcxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDcyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDczIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDc0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDc1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDc2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDc3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDc4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDc5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDdBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDdCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDdDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDdEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDdFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDdGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDgwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDgxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDgyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDgzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDg0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDg1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDg2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDg3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDg4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDg5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDhBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDhCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDhDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDhEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDhFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDhGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDkwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDkxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDkyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDkzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDk0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDk1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDk2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDk3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDk4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDk5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDlBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDlCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDlDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDlEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDlFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMDlGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEEwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEExIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEEyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEEzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEE0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEE1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEE2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEE3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEE4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEE5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEFBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEFCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEFDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEFEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEFFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEFGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEIwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEIxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEIyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEIzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEI0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEI1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEI2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEI3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEI4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEI5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEJBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEJCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEJDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEJEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEJFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEJGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEMwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEMxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEMyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEMzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEM0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEM1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEM2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEM3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEM4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEM5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMENBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMENCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMENDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMENEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMENFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMENGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQ0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQ1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQ2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQ3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQ4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEQ5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMERBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMERCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMERDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEREIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMERFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMERGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEUwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEUxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEUyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEUzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEU0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEU1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEU2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEU3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEU4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEU5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEVBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEVCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEVDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEVEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEVFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEVGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEYwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEYxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEYyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEYzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEY0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEY1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEY2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEY3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEY4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEY5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEZBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEZCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEZDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEZEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEZFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMEZGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTAwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTAxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTAyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTAzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTA0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTA1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTA2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTA3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTA4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTA5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTBBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTBCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTBDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTBEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTBFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTBGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTEwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTExIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTEyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTEzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTE0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTE1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTE2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTE3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTE4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTE5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTFBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTFCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTFDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTFEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTFFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTFGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTIwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTIxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTIyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTIzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTI0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTI1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTI2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTI3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTI4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTI5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTJBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTJCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTJDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTJEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTJFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTJGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTMwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTMxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTMyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTMzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTM0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTM1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTM2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTM3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTM4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTM5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTNBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTNCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTNDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTNEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTNFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTNGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQ0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQ1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQ2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQ3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQ4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTQ5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTRBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTRCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTRDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTREIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTRFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTRGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTUwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTUxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTUyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTUzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTU0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTU1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTU2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTU3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTU4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTU5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTVBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTVCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTVDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTVEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTVFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTVGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTYwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTYxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTYyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTYzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTY0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTY1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTY2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTY3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTY4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTY5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTZBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTZCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTZDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTZEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTZFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTZGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTcwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTcxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTcyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTczIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTc0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTc1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTc2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTc3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTc4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTc5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTdBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTdCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTdDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTdEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTdFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTdGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTgwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTgxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTgyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTgzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTg0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTg1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTg2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTg3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTg4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTg5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMThBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMThCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMThDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMThEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMThFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMThGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTkwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTkxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTkyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTkzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTk0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTk1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTk2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTk3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTk4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTk5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTlBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTlCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTlDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTlEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTlFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMTlGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUEwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUExIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUEyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUEzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUE0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUE1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUE2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUE3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUE4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUE5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUFBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUFCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUFDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUFEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUFFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUFGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUIwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUIxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUIyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUIzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUI0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUI1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUI2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUI3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUI4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUI5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUJBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUJCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUJDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUJEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUJFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUJGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUMwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUMxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUMyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUMzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUM0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUM1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUM2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUM3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUM4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUM5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUNBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUNCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUNDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUNEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUNFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUNGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQ0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQ1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQ2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQ3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQ4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUQ5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMURBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMURCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMURDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUREIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMURFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMURGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUUwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUUxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUUyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUUzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUU0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUU1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUU2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUU3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUU4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUU5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUVBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUVCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUVDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUVEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUVFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUVGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUYwIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUYxIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUYyIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUYzIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUY0IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUY1IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUY2IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUY3IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUY4IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUY5IG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUZBIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUZCIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUZDIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUZEIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUZFIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMUZGIG5vcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg5MCwNCisgIC8qIDAwMDAwMjAwIGNtcCBheCwweDRmMDAgICAgICAgICAgICAgICAgICAqLyAg
MHgzRCwgMHgwMCwgMHg0RiwNCisgIC8qIDAwMDAwMjAzIGp6IDB4MjM3ICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg3NCwgMHgzMiwNCisgIC8qIDAwMDAwMjA1IGNtcCBheCwweDRmMDEgICAg
ICAgICAgICAgICAgICAqLyAgMHgzRCwgMHgwMSwgMHg0RiwNCisgIC8qIDAwMDAwMjA4IGp6IDB4
MjU3ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NCwgMHg0RCwNCisgIC8qIDAwMDAwMjBB
IGNtcCBheCwweDRmMDIgICAgICAgICAgICAgICAgICAqLyAgMHgzRCwgMHgwMiwgMHg0RiwNCisg
IC8qIDAwMDAwMjBEIGp6IG5lYXIgMHgyYzggICAgICAgICAgICAgICAgICAqLyAgMHgwRiwgMHg4
NCwgMHhCNywgMHgwMCwNCisgIC8qIDAwMDAwMjExIGNtcCBheCwweDRmMDMgICAgICAgICAgICAg
ICAgICAqLyAgMHgzRCwgMHgwMywgMHg0RiwNCisgIC8qIDAwMDAwMjE0IGp6IG5lYXIgMHgzMjUg
ICAgICAgICAgICAgICAgICAqLyAgMHgwRiwgMHg4NCwgMHgwRCwgMHgwMSwNCisgIC8qIDAwMDAw
MjE4IGNtcCBheCwweDRmMTAgICAgICAgICAgICAgICAgICAqLyAgMHgzRCwgMHgxMCwgMHg0RiwN
CisgIC8qIDAwMDAwMjFCIGp6IG5lYXIgMHgzMzcgICAgICAgICAgICAgICAgICAqLyAgMHgwRiwg
MHg4NCwgMHgxOCwgMHgwMSwNCisgIC8qIDAwMDAwMjFGIGNtcCBheCwweDRmMTUgICAgICAgICAg
ICAgICAgICAqLyAgMHgzRCwgMHgxNSwgMHg0RiwNCisgIC8qIDAwMDAwMjIyIGp6IG5lYXIgMHgz
NDQgICAgICAgICAgICAgICAgICAqLyAgMHgwRiwgMHg4NCwgMHgxRSwgMHgwMSwNCisgIC8qIDAw
MDAwMjI2IGNtcCBhaCwweDAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg4MCwgMHhGQywgMHgw
MCwNCisgIC8qIDAwMDAwMjI5IGp6IG5lYXIgMHgzNjMgICAgICAgICAgICAgICAgICAqLyAgMHgw
RiwgMHg4NCwgMHgzNiwgMHgwMSwNCisgIC8qIDAwMDAwMjJEIHB1c2ggc2kgICAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMjJFIG1vdiBzaSwweDNkNyAgICAgICAg
ICAgICAgICAgICAqLyAgMHhCRSwgMHhENywgMHgwMywNCisgIC8qIDAwMDAwMjMxIGNhbGwgMHgz
YWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHg3OSwgMHgwMSwNCisgIC8qIDAwMDAw
MjM0IHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAw
MjM1IGptcCBzaG9ydCAweDIzNSAgICAgICAgICAgICAgICAqLyAgMHhFQiwgMHhGRSwNCisgIC8q
IDAwMDAwMjM3IHB1c2ggZXMgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgwNiwNCisgIC8q
IDAwMDAwMjM4IHB1c2ggZGkgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NywNCisgIC8q
IDAwMDAwMjM5IHB1c2ggZHMgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgxRSwNCisgIC8q
IDAwMDAwMjNBIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8q
IDAwMDAwMjNCIHB1c2ggY3ggICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1MSwNCisgIC8q
IDAwMDAwMjNDIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8q
IDAwMDAwMjNEIG1vdiBzaSwweDNlYiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHhFQiwg
MHgwMywNCisgIC8qIDAwMDAwMjQwIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAg
MHhFOCwgMHg2QSwgMHgwMSwNCisgIC8qIDAwMDAwMjQzIHBvcCBzaSAgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMjQ0IHB1c2ggY3MgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHgwRSwNCisgIC8qIDAwMDAwMjQ1IHBvcCBkcyAgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHgxRiwNCisgIC8qIDAwMDAwMjQ2IG1vdiBzaSwweDAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHhCRSwgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwMjQ5IG1vdiBjeCwweDEw
MCAgICAgICAgICAgICAgICAgICAqLyAgMHhCOSwgMHgwMCwgMHgwMSwNCisgIC8qIDAwMDAwMjRD
IGNsZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhGQywNCisgIC8qIDAwMDAwMjRE
IHJlcCBtb3ZzYiAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhGMywgMHhBNCwNCisgIC8qIDAw
MDAwMjRGIHBvcCBjeCAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1OSwNCisgIC8qIDAw
MDAwMjUwIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAw
MDAwMjUxIHBvcCBkcyAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgxRiwNCisgIC8qIDAw
MDAwMjUyIHBvcCBkaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RiwNCisgIC8qIDAw
MDAwMjUzIHBvcCBlcyAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgwNywNCisgIC8qIDAw
MDAwMjU0IGptcCAweDM5NSAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOSwgMHgzRSwgMHgw
MSwNCisgIC8qIDAwMDAwMjU3IHB1c2ggZXMgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgw
NiwNCisgIC8qIDAwMDAwMjU4IHB1c2ggZGkgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
NywNCisgIC8qIDAwMDAwMjU5IHB1c2ggZHMgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgx
RSwNCisgIC8qIDAwMDAwMjVBIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
NiwNCisgIC8qIDAwMDAwMjVCIHB1c2ggY3ggICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
MSwNCisgIC8qIDAwMDAwMjVDIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
NiwNCisgIC8qIDAwMDAwMjVEIG1vdiBzaSwweDNmNiAgICAgICAgICAgICAgICAgICAqLyAgMHhC
RSwgMHhGNiwgMHgwMywNCisgIC8qIDAwMDAwMjYwIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHhFOCwgMHg0QSwgMHgwMSwNCisgIC8qIDAwMDAwMjYzIHBvcCBzaSAgICAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMjY0IGFuZCBjeCwweGJmZmYg
ICAgICAgICAgICAgICAgICAqLyAgMHg4MSwgMHhFMSwgMHhGRiwgMHhCRiwNCisgIC8qIDAwMDAw
MjY4IGNtcCBjeCwweDEzZiAgICAgICAgICAgICAgICAgICAqLyAgMHg4MSwgMHhGOSwgMHgzRiwg
MHgwMSwNCisgIC8qIDAwMDAwMjZDIGp6IDB4Mjg0ICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg3NCwgMHgxNiwNCisgIC8qIDAwMDAwMjZFIGNtcCBjeCwweDE0MCAgICAgICAgICAgICAgICAg
ICAqLyAgMHg4MSwgMHhGOSwgMHg0MCwgMHgwMSwNCisgIC8qIDAwMDAwMjcyIGp6IDB4MjkxICAg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NCwgMHgxRCwNCisgIC8qIDAwMDAwMjc0IGNtcCBj
eCwweDE0MSAgICAgICAgICAgICAgICAgICAqLyAgMHg4MSwgMHhGOSwgMHg0MSwgMHgwMSwNCisg
IC8qIDAwMDAwMjc4IGp6IDB4MjllICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NCwgMHgy
NCwNCisgIC8qIDAwMDAwMjdBIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
NiwNCisgIC8qIDAwMDAwMjdCIG1vdiBzaSwweDQyYyAgICAgICAgICAgICAgICAgICAqLyAgMHhC
RSwgMHgyQywgMHgwNCwNCisgIC8qIDAwMDAwMjdFIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHhFOCwgMHgyQywgMHgwMSwNCisgIC8qIDAwMDAwMjgxIHBvcCBzaSAgICAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMjgyIGptcCBzaG9ydCAweDIz
NSAgICAgICAgICAgICAgICAqLyAgMHhFQiwgMHhCMSwNCisgIC8qIDAwMDAwMjg0IHB1c2ggc2kg
ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMjg1IG1vdiBzaSww
eDQ2YiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHg2QiwgMHgwNCwNCisgIC8qIDAwMDAw
Mjg4IGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHgyMiwgMHgwMSwN
CisgIC8qIDAwMDAwMjhCIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwN
CisgIC8qIDAwMDAwMjhDIG1vdiBzaSwweDEwMCAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwg
MHgwMCwgMHgwMSwNCisgIC8qIDAwMDAwMjhGIGptcCBzaG9ydCAweDJiOCAgICAgICAgICAgICAg
ICAqLyAgMHhFQiwgMHgyNywNCisgIC8qIDAwMDAwMjkxIHB1c2ggc2kgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMjkyIG1vdiBzaSwweDQ3ZCAgICAgICAgICAg
ICAgICAgICAqLyAgMHhCRSwgMHg3RCwgMHgwNCwNCisgIC8qIDAwMDAwMjk1IGNhbGwgMHgzYWQg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHgxNSwgMHgwMSwNCisgIC8qIDAwMDAwMjk4
IHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMjk5
IG1vdiBzaSwweDEzMiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHgzMiwgMHgwMSwNCisg
IC8qIDAwMDAwMjlDIGptcCBzaG9ydCAweDJiOCAgICAgICAgICAgICAgICAqLyAgMHhFQiwgMHgx
QSwNCisgIC8qIDAwMDAwMjlFIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
NiwNCisgIC8qIDAwMDAwMjlGIG1vdiBzaSwweDQ4ZiAgICAgICAgICAgICAgICAgICAqLyAgMHhC
RSwgMHg4RiwgMHgwNCwNCisgIC8qIDAwMDAwMkEyIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHhFOCwgMHgwOCwgMHgwMSwNCisgIC8qIDAwMDAwMkE1IHBvcCBzaSAgICAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMkE2IG1vdiBzaSwweDE2NCAg
ICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHg2NCwgMHgwMSwNCisgIC8qIDAwMDAwMkE5IGpt
cCBzaG9ydCAweDJiOCAgICAgICAgICAgICAgICAqLyAgMHhFQiwgMHgwRCwNCisgIC8qIDAwMDAw
MkFCIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAw
MkFDIG1vdiBzaSwweDRhMiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHhBMiwgMHgwNCwN
CisgIC8qIDAwMDAwMkFGIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwg
MHhGQiwgMHgwMCwNCisgIC8qIDAwMDAwMkIyIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAg
ICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMkIzIG1vdiBzaSwweDE5NiAgICAgICAgICAgICAgICAg
ICAqLyAgMHhCRSwgMHg5NiwgMHgwMSwNCisgIC8qIDAwMDAwMkI2IGptcCBzaG9ydCAweDJiOCAg
ICAgICAgICAgICAgICAqLyAgMHhFQiwgMHgwMCwNCisgIC8qIDAwMDAwMkI4IHB1c2ggY3MgICAg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHgwRSwNCisgIC8qIDAwMDAwMkI5IHBvcCBkcyAgICAg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHgxRiwNCisgIC8qIDAwMDAwMkJBIG1vdiBjeCwweDMy
ICAgICAgICAgICAgICAgICAgICAqLyAgMHhCOSwgMHgzMiwgMHgwMCwNCisgIC8qIDAwMDAwMkJE
IGNsZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhGQywNCisgIC8qIDAwMDAwMkJF
IHJlcCBtb3ZzYiAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhGMywgMHhBNCwNCisgIC8qIDAw
MDAwMkMwIHBvcCBjeCAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1OSwNCisgIC8qIDAw
MDAwMkMxIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAw
MDAwMkMyIHBvcCBkcyAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgxRiwNCisgIC8qIDAw
MDAwMkMzIHBvcCBkaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RiwNCisgIC8qIDAw
MDAwMkM0IHBvcCBlcyAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgwNywNCisgIC8qIDAw
MDAwMkM1IGptcCAweDM5NSAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOSwgMHhDRCwgMHgw
MCwNCisgIC8qIDAwMDAwMkM4IHB1c2ggZHggICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
MiwNCisgIC8qIDAwMDAwMkM5IHB1c2ggYXggICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
MCwNCisgIC8qIDAwMDAwMkNBIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
NiwNCisgIC8qIDAwMDAwMkNCIG1vdiBzaSwweDQxMCAgICAgICAgICAgICAgICAgICAqLyAgMHhC
RSwgMHgxMCwgMHgwNCwNCisgIC8qIDAwMDAwMkNFIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHhFOCwgMHhEQywgMHgwMCwNCisgIC8qIDAwMDAwMkQxIHBvcCBzaSAgICAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMkQyIGFuZCBieCwweGJmZmYg
ICAgICAgICAgICAgICAgICAqLyAgMHg4MSwgMHhFMywgMHhGRiwgMHhCRiwNCisgIC8qIDAwMDAw
MkQ2IGNtcCBieCwweDEzZiAgICAgICAgICAgICAgICAgICAqLyAgMHg4MSwgMHhGQiwgMHgzRiwg
MHgwMSwNCisgIC8qIDAwMDAwMkRBIGp6IDB4MmYzICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg3NCwgMHgxNywNCisgIC8qIDAwMDAwMkRDIGNtcCBieCwweDE0MCAgICAgICAgICAgICAgICAg
ICAqLyAgMHg4MSwgMHhGQiwgMHg0MCwgMHgwMSwNCisgIC8qIDAwMDAwMkUwIGp6IDB4MmZkICAg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NCwgMHgxQiwNCisgIC8qIDAwMDAwMkUyIGNtcCBi
eCwweDE0MSAgICAgICAgICAgICAgICAgICAqLyAgMHg4MSwgMHhGQiwgMHg0MSwgMHgwMSwNCisg
IC8qIDAwMDAwMkU2IGp6IDB4MzA3ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NCwgMHgx
RiwNCisgIC8qIDAwMDAwMkU4IHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
NiwNCisgIC8qIDAwMDAwMkU5IG1vdiBzaSwweDQyYyAgICAgICAgICAgICAgICAgICAqLyAgMHhC
RSwgMHgyQywgMHgwNCwNCisgIC8qIDAwMDAwMkVDIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHhFOCwgMHhCRSwgMHgwMCwNCisgIC8qIDAwMDAwMkVGIHBvcCBzaSAgICAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMkYwIGptcCAweDIzNSAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHhFOSwgMHg0MiwgMHhGRiwNCisgIC8qIDAwMDAwMkYzIHB1
c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMkY0IG1v
diBzaSwweDQ2YiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHg2QiwgMHgwNCwNCisgIC8q
IDAwMDAwMkY3IGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHhCMywg
MHgwMCwNCisgIC8qIDAwMDAwMkZBIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg1RSwNCisgIC8qIDAwMDAwMkZCIGptcCBzaG9ydCAweDMxOSAgICAgICAgICAgICAgICAqLyAg
MHhFQiwgMHgxQywNCisgIC8qIDAwMDAwMkZEIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAg
ICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMkZFIG1vdiBzaSwweDQ3ZCAgICAgICAgICAgICAgICAg
ICAqLyAgMHhCRSwgMHg3RCwgMHgwNCwNCisgIC8qIDAwMDAwMzAxIGNhbGwgMHgzYWQgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHhFOCwgMHhBOSwgMHgwMCwNCisgIC8qIDAwMDAwMzA0IHBvcCBz
aSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMzA1IGptcCBz
aG9ydCAweDMxOSAgICAgICAgICAgICAgICAqLyAgMHhFQiwgMHgxMiwNCisgIC8qIDAwMDAwMzA3
IHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzA4
IG1vdiBzaSwweDQ4ZiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHg4RiwgMHgwNCwNCisg
IC8qIDAwMDAwMzBCIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHg5
RiwgMHgwMCwNCisgIC8qIDAwMDAwMzBFIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAq
LyAgMHg1RSwNCisgIC8qIDAwMDAwMzBGIGptcCBzaG9ydCAweDMxOSAgICAgICAgICAgICAgICAq
LyAgMHhFQiwgMHgwOCwNCisgIC8qIDAwMDAwMzExIHB1c2ggc2kgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzEyIG1vdiBzaSwweDRhMiAgICAgICAgICAgICAg
ICAgICAqLyAgMHhCRSwgMHhBMiwgMHgwNCwNCisgIC8qIDAwMDAwMzE1IGNhbGwgMHgzYWQgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHg5NSwgMHgwMCwNCisgIC8qIDAwMDAwMzE4IHBv
cCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMzE5IG1v
diBbMHg0YjBdLGJsICAgICAgICAgICAgICAgICAqLyAgMHg4OCwgMHgxRSwgMHhCMCwgMHgwNCwN
CisgIC8qIDAwMDAwMzFEIG1vdiBbMHg0YjFdLGJoICAgICAgICAgICAgICAgICAqLyAgMHg4OCwg
MHgzRSwgMHhCMSwgMHgwNCwNCisgIC8qIDAwMDAwMzIxIHBvcCBheCAgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1OCwNCisgIC8qIDAwMDAwMzIyIHBvcCBkeCAgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1QSwNCisgIC8qIDAwMDAwMzIzIGptcCBzaG9ydCAweDM5NSAgICAgICAg
ICAgICAgICAqLyAgMHhFQiwgMHg3MCwNCisgIC8qIDAwMDAwMzI1IHB1c2ggc2kgICAgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzI2IG1vdiBzaSwweDQwNSAgICAg
ICAgICAgICAgICAgICAqLyAgMHhCRSwgMHgwNSwgMHgwNCwNCisgIC8qIDAwMDAwMzI5IGNhbGwg
MHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHg4MSwgMHgwMCwNCisgIC8qIDAw
MDAwMzJDIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAw
MDAwMzJEIG1vdiBibCxbMHg0YjBdICAgICAgICAgICAgICAgICAqLyAgMHg4QSwgMHgxRSwgMHhC
MCwgMHgwNCwNCisgIC8qIDAwMDAwMzMxIG1vdiBiaCxbMHg0YjFdICAgICAgICAgICAgICAgICAq
LyAgMHg4QSwgMHgzRSwgMHhCMSwgMHgwNCwNCisgIC8qIDAwMDAwMzM1IGptcCBzaG9ydCAweDM5
NSAgICAgICAgICAgICAgICAqLyAgMHhFQiwgMHg1RSwNCisgIC8qIDAwMDAwMzM3IHB1c2ggc2kg
ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzM4IG1vdiBzaSww
eDQzYiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHgzQiwgMHgwNCwNCisgIC8qIDAwMDAw
MzNCIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHg2RiwgMHgwMCwN
CisgIC8qIDAwMDAwMzNFIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwN
CisgIC8qIDAwMDAwMzNGIG1vdiBieCwweDgwICAgICAgICAgICAgICAgICAgICAqLyAgMHhCQiwg
MHg4MCwgMHgwMCwNCisgIC8qIDAwMDAwMzQyIGptcCBzaG9ydCAweDM5NSAgICAgICAgICAgICAg
ICAqLyAgMHhFQiwgMHg1MSwNCisgIC8qIDAwMDAwMzQ0IHB1c2ggZXMgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHgwNiwNCisgIC8qIDAwMDAwMzQ1IHB1c2ggZGkgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1NywNCisgIC8qIDAwMDAwMzQ2IHB1c2ggZHMgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHgxRSwNCisgIC8qIDAwMDAwMzQ3IHB1c2ggc2kgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzQ4IHB1c2ggY3ggICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1MSwNCisgIC8qIDAwMDAwMzQ5IHB1c2ggc2kgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzRBIG1vdiBzaSwweDQ1MCAgICAgICAgICAg
ICAgICAgICAqLyAgMHhCRSwgMHg1MCwgMHgwNCwNCisgIC8qIDAwMDAwMzREIGNhbGwgMHgzYWQg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHg1RCwgMHgwMCwNCisgIC8qIDAwMDAwMzUw
IHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMzUx
IHB1c2ggY3MgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgwRSwNCisgIC8qIDAwMDAwMzUy
IHBvcCBkcyAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgxRiwNCisgIC8qIDAwMDAwMzUz
IG1vdiBzaSwweDRiMiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHhCMiwgMHgwNCwNCisg
IC8qIDAwMDAwMzU2IG1vdiBjeCwweDgwICAgICAgICAgICAgICAgICAgICAqLyAgMHhCOSwgMHg4
MCwgMHgwMCwNCisgIC8qIDAwMDAwMzU5IGNsZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAq
LyAgMHhGQywNCisgIC8qIDAwMDAwMzVBIHJlcCBtb3ZzYiAgICAgICAgICAgICAgICAgICAgICAq
LyAgMHhGMywgMHhBNCwNCisgIC8qIDAwMDAwMzVDIHBvcCBjeCAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg1OSwNCisgIC8qIDAwMDAwMzVEIHBvcCBzaSAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMzVFIHBvcCBkcyAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHgxRiwNCisgIC8qIDAwMDAwMzVGIHBvcCBkaSAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg1RiwNCisgIC8qIDAwMDAwMzYwIHBvcCBlcyAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHgwNywNCisgIC8qIDAwMDAwMzYxIGptcCBzaG9ydCAweDM5NSAgICAgICAgICAg
ICAgICAqLyAgMHhFQiwgMHgzMiwNCisgIC8qIDAwMDAwMzYzIHB1c2ggc2kgICAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzY0IG1vdiBzaSwweDQxYiAgICAgICAg
ICAgICAgICAgICAqLyAgMHhCRSwgMHgxQiwgMHgwNCwNCisgIC8qIDAwMDAwMzY3IGNhbGwgMHgz
YWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHg0MywgMHgwMCwNCisgIC8qIDAwMDAw
MzZBIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAw
MzZCIGNtcCBhbCwweDMgICAgICAgICAgICAgICAgICAgICAqLyAgMHgzQywgMHgwMywNCisgIC8q
IDAwMDAwMzZEIGp6IDB4MzdlICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NCwgMHgwRiwN
CisgIC8qIDAwMDAwMzZGIGNtcCBhbCwweDEyICAgICAgICAgICAgICAgICAgICAqLyAgMHgzQywg
MHgxMiwNCisgIC8qIDAwMDAwMzcxIGp6IDB4MzhhICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg3NCwgMHgxNywNCisgIC8qIDAwMDAwMzczIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAg
ICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzc0IG1vdiBzaSwweDQyYyAgICAgICAgICAgICAgICAg
ICAqLyAgMHhCRSwgMHgyQywgMHgwNCwNCisgIC8qIDAwMDAwMzc3IGNhbGwgMHgzYWQgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHhFOCwgMHgzMywgMHgwMCwNCisgIC8qIDAwMDAwMzdBIHBvcCBz
aSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMzdCIGptcCAw
eDIzNSAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOSwgMHhCNywgMHhGRSwNCisgIC8qIDAw
MDAwMzdFIHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAw
MDAwMzdGIG1vdiBzaSwweDQ1YyAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHg1QywgMHgw
NCwNCisgIC8qIDAwMDAwMzgyIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhF
OCwgMHgyOCwgMHgwMCwNCisgIC8qIDAwMDAwMzg1IHBvcCBzaSAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMzg2IG1vdiBhbCwweDAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHhCMCwgMHgwMCwNCisgIC8qIDAwMDAwMzg4IGptcCBzaG9ydCAweDM4YyAgICAg
ICAgICAgICAgICAqLyAgMHhFQiwgMHgwMiwNCisgIC8qIDAwMDAwMzhBIG1vdiBhbCwweDAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHhCMCwgMHgwMCwNCisgIC8qIDAwMDAwMzhDIHB1c2ggc2kg
ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwMzhEIG1vdiBzaSww
eDNjMiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHhDMiwgMHgwMywNCisgIC8qIDAwMDAw
MzkwIGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHgxQSwgMHgwMCwN
CisgIC8qIDAwMDAwMzkzIHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1RSwN
CisgIC8qIDAwMDAwMzk0IGlyZXQgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhDRiwN
CisgIC8qIDAwMDAwMzk1IHB1c2ggc2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwN
CisgIC8qIDAwMDAwMzk2IG1vdiBzaSwweDNjMiAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwg
MHhDMiwgMHgwMywNCisgIC8qIDAwMDAwMzk5IGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAg
ICAqLyAgMHhFOCwgMHgxMSwgMHgwMCwNCisgIC8qIDAwMDAwMzlDIHBvcCBzaSAgICAgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHg1RSwNCisgIC8qIDAwMDAwMzlEIG1vdiBheCwweDRmICAgICAg
ICAgICAgICAgICAgICAqLyAgMHhCOCwgMHg0RiwgMHgwMCwNCisgIC8qIDAwMDAwM0EwIGlyZXQg
ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhDRiwNCisgIC8qIDAwMDAwM0ExIHB1c2gg
c2kgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1NiwNCisgIC8qIDAwMDAwM0EyIG1vdiBz
aSwweDNjOCAgICAgICAgICAgICAgICAgICAqLyAgMHhCRSwgMHhDOCwgMHgwMywNCisgIC8qIDAw
MDAwM0E1IGNhbGwgMHgzYWQgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFOCwgMHgwNSwgMHgw
MCwNCisgIC8qIDAwMDAwM0E4IHBvcCBzaSAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg1
RSwNCisgIC8qIDAwMDAwM0E5IG1vdiBheCwweDI0ZiAgICAgICAgICAgICAgICAgICAqLyAgMHhC
OCwgMHg0RiwgMHgwMiwNCisgIC8qIDAwMDAwM0FDIGlyZXQgICAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHhDRiwNCisgIC8qIDAwMDAwM0FEIHB1c2hhICAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg2MCwNCisgIC8qIDAwMDAwM0FFIHB1c2ggZHMgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHgxRSwNCisgIC8qIDAwMDAwM0FGIHB1c2ggY3MgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHgwRSwNCisgIC8qIDAwMDAwM0IwIHBvcCBkcyAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHgxRiwNCisgIC8qIDAwMDAwM0IxIG1vdiBkeCwweDIyMCAgICAgICAgICAgICAg
ICAgICAqLyAgMHhCQSwgMHgyMCwgMHgwMiwNCisgIC8qIDAwMDAwM0I0IG1vdiBheCwweDAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHhCOCwgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwM0I3IGxv
ZHNiICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhBQywNCisgIC8qIDAwMDAwM0I4IGNt
cCBhbCwweDAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgzQywgMHgwMCwNCisgIC8qIDAwMDAw
M0JBIGp6IDB4M2JmICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NCwgMHgwMywNCisgIC8q
IDAwMDAwM0JDIG91dCBkeCxhbCAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhFRSwNCisgIC8q
IDAwMDAwM0JEIGptcCBzaG9ydCAweDNiNyAgICAgICAgICAgICAgICAqLyAgMHhFQiwgMHhGOCwN
CisgIC8qIDAwMDAwM0JGIHBvcCBkcyAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgxRiwN
CisgIC8qIDAwMDAwM0MwIHBvcGEgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2MSwN
CisgIC8qIDAwMDAwM0MxIHJldCAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHhDMywN
CisgIC8qIDAwMDAwM0MyIGpuYSAweDQxMyAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3Niwg
MHg0RiwNCisgIC8qIDAwMDAwM0M0IGltdWwgY3gsW2RpXSxieXRlICsweGEgICAgICAgICAqLyAg
MHg2QiwgMHgwRCwgMHgwQSwNCisgIC8qIDAwMDAwM0M3IGFkZCBbYnArMHg1NV0sZGggICAgICAg
ICAgICAgICAqLyAgMHgwMCwgMHg3NiwgMHg1NSwNCisgIC8qIDAwMDAwM0NBIG91dHNiICAgICAg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RSwNCisgIC8qIDAwMDAwM0NCIGpuYyAweDQ0MiAg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHg3MywgMHg3NSwNCisgIC8qIDAwMDAwM0NEIGpvIDB4
NDNmICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3MCwgMHg3MCwNCisgIC8qIDAwMDAwM0NG
IG91dHN3ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RiwNCisgIC8qIDAwMDAwM0Qw
IGpjIDB4NDQ2ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3MiwgMHg3NCwNCisgIC8qIDAw
MDAwM0QyIGZzIG9yIGF4LDB4YSAgICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg2NCwgMHgw
RCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwM0Q3IGpuYSAweDQyZSAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg3NiwgMHg1NSwNCisgIC8qIDAwMDAwM0Q5IG91dHNiICAgICAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2RSwNCisgIC8qIDAwMDAwM0RBIGltdWwgYnAsW2JwKzB4NmZdLGJ5
dGUgKzB4NzcgICAqLyAgMHg2QiwgMHg2RSwgMHg2RiwgMHg3NywNCisgIC8qIDAwMDAwM0RFIG91
dHNiICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RSwNCisgIC8qIDAwMDAwM0RGIGFu
ZCBbYnArMHg3NV0sYWwgICAgICAgICAgICAgICAqLyAgMHgyMCwgMHg0NiwgMHg3NSwNCisgIC8q
IDAwMDAwM0UyIG91dHNiICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RSwNCisgIC8q
IDAwMDAwM0UzIGFycGwgW3NpKzB4NjldLHNpICAgICAgICAgICAgICAqLyAgMHg2MywgMHg3NCwg
MHg2OSwNCisgIC8qIDAwMDAwM0U2IG91dHN3ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg2RiwNCisgIC8qIDAwMDAwM0U3IG91dHNiICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg2RSwNCisgIC8qIDAwMDAwM0U4IG9yIGF4LDB4YSAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHgwRCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwM0VCIGpuYSAweDQzNCAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg3NiwgMHg0NywNCisgIC8qIDAwMDAwM0VEIGdzIGp6IDB4NDM5ICAgICAg
ICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg3NCwgMHg0OSwNCisgIC8qIDAwMDAwM0YwIG91dHNi
ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RSwNCisgIC8qIDAwMDAwM0YxIG91dHNk
ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NiwgMHg2RiwNCisgIC8qIDAwMDAwM0Yz
IG9yIGF4LDB4YSAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgwRCwgMHgwQSwgMHgwMCwNCisg
IC8qIDAwMDAwM0Y2IGpuYSAweDQzZiAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NiwgMHg0
NywNCisgIC8qIDAwMDAwM0Y4IGdzIGp6IDB4NDQ4ICAgICAgICAgICAgICAgICAgICAqLyAgMHg2
NSwgMHg3NCwgMHg0RCwNCisgIC8qIDAwMDAwM0ZCIG91dHN3ICAgICAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg2RiwNCisgIC8qIDAwMDAwM0ZDIGdzIGRlYyBjeCAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg2NCwgMHg2NSwgMHg0OSwNCisgIC8qIDAwMDAwM0ZGIG91dHNiICAgICAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg2RSwNCisgIC8qIDAwMDAwNDAwIG91dHNkICAgICAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg2NiwgMHg2RiwNCisgIC8qIDAwMDAwNDAyIG9yIGF4LDB4
YSAgICAgICAgICAgICAgICAgICAgICAqLyAgMHgwRCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAw
NDA1IGpuYSAweDQ0ZSAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NiwgMHg0NywNCisgIC8q
IDAwMDAwNDA3IGdzIGp6IDB4NDU3ICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg3NCwg
MHg0RCwNCisgIC8qIDAwMDAwNDBBIG91dHN3ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAg
MHg2RiwNCisgIC8qIDAwMDAwNDBCIGdzIG9yIGF4LDB4YSAgICAgICAgICAgICAgICAgICAqLyAg
MHg2NCwgMHg2NSwgMHgwRCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDEwIGpuYSAweDQ2NSAg
ICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NiwgMHg1MywNCisgIC8qIDAwMDAwNDEyIGdzIGp6
IDB4NDYyICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg3NCwgMHg0RCwNCisgIC8qIDAw
MDAwNDE1IG91dHN3ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RiwNCisgIC8qIDAw
MDAwNDE2IGdzIG9yIGF4LDB4YSAgICAgICAgICAgICAgICAgICAqLyAgMHg2NCwgMHg2NSwgMHgw
RCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDFCIGpuYSAweDQ3MCAgICAgICAgICAgICAgICAg
ICAgICAqLyAgMHg3NiwgMHg1MywNCisgIC8qIDAwMDAwNDFEIGdzIGp6IDB4NDZkICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2NSwgMHg3NCwgMHg0RCwNCisgIC8qIDAwMDAwNDIwIG91dHN3ICAg
ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RiwNCisgIC8qIDAwMDAwNDIxIGdzIGRlYyBz
cCAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NCwgMHg2NSwgMHg0QywNCisgIC8qIDAwMDAw
NDI0IGdzIGEzMiBwb3BhICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg2NywgMHg2MSwN
CisgIC8qIDAwMDAwNDI3IGFycGwgW2J4K2RpKzB4ZF0sZGkgICAgICAgICAgICAqLyAgMHg2Mywg
MHg3OSwgMHgwRCwNCisgIC8qIDAwMDAwNDJBIG9yIGFsLFtieCtzaV0gICAgICAgICAgICAgICAg
ICAqLyAgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDJDIGpuYSAweDQ4MyAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg3NiwgMHg1NSwNCisgIC8qIDAwMDAwNDJFIG91dHNiICAgICAgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHg2RSwNCisgIC8qIDAwMDAwNDJGIGltdWwgYnAsW2J4KzB4Nzdd
LGJ5dGUgKzB4NmUgICAqLyAgMHg2QiwgMHg2RiwgMHg3NywgMHg2RSwNCisgIC8qIDAwMDAwNDMz
IGFuZCBbZGkrMHg2Zl0sY2wgICAgICAgICAgICAgICAqLyAgMHgyMCwgMHg0RCwgMHg2RiwNCisg
IC8qIDAwMDAwNDM2IGdzIG9yIGF4LDB4YSAgICAgICAgICAgICAgICAgICAqLyAgMHg2NCwgMHg2
NSwgMHgwRCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDNCIGpuYSAweDQ4NCAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg3NiwgMHg0NywNCisgIC8qIDAwMDAwNDNEIGdzIGp6IDB4NDkwICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg3NCwgMHg1MCwNCisgIC8qIDAwMDAwNDQwIGlu
c3cgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RCwNCisgIC8qIDAwMDAwNDQxIGlu
YyBieCAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg0MywNCisgIC8qIDAwMDAwNDQyIHBv
cGEgICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2MSwNCisgIC8qIDAwMDAwNDQzIGpv
IDB4NGE2ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3MCwgMHg2MSwNCisgIC8qIDAwMDAw
NDQ1IGJvdW5kIGJwLFtieCtkaSsweDZjXSAgICAgICAgICAqLyAgMHg2MiwgMHg2OSwgMHg2QywN
CisgIC8qIDAwMDAwNDQ4IGltdWwgc2ksW3NpKzB4NjldLHdvcmQgMHg3MzY1ICAqLyAgMHg2OSwg
MHg3NCwgMHg2OSwgMHg2NSwgMHg3MywNCisgIC8qIDAwMDAwNDREIG9yIGF4LDB4YSAgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHgwRCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDUwIGpuYSAw
eDRhNCAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NiwgMHg1MiwNCisgIC8qIDAwMDAwNDUy
IGdzIHBvcGEgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg2MSwNCisgIC8qIDAw
MDAwNDU0IGZzIGluYyBicCAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NCwgMHg0NSwNCisg
IC8qIDAwMDAwNDU2IGltdWwgc3AsW2ZzOnNpKzB4ZF0sd29yZCAweGEgICAqLyAgMHg2NCwgMHg2
OSwgMHg2NCwgMHgwRCwgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDVDIGpuYSAweDRhYSAgICAg
ICAgICAgICAgICAgICAgICAqLyAgMHg3NiwgMHg0QywNCisgIC8qIDAwMDAwNDVFIGdzIGEzMiBw
b3BhICAgICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg2NywgMHg2MSwNCisgIC8qIDAwMDAw
NDYxIGFycGwgW2J4K2RpKzB4NGRdLGRpICAgICAgICAgICAqLyAgMHg2MywgMHg3OSwgMHg0RCwN
CisgIC8qIDAwMDAwNDY0IG91dHN3ICAgICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg2RiwN
CisgIC8qIDAwMDAwNDY1IHhvciBjeCxbZ3M6ZGldICAgICAgICAgICAgICAgICAqLyAgMHg2NCwg
MHg2NSwgMHgzMywgMHgwRCwNCisgIC8qIDAwMDAwNDY5IG9yIGFsLFtieCtzaV0gICAgICAgICAg
ICAgICAgICAqLyAgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDZCIGluc3cgICAgICAgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHg2RCwNCisgIC8qIDAwMDAwNDZDIG91dHN3ICAgICAgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHg2RiwNCisgIC8qIDAwMDAwNDZEIGdzIHBvcCBkaSAgICAgICAg
ICAgICAgICAgICAgICAqLyAgMHg2NCwgMHg2NSwgMHg1RiwNCisgIC8qIDAwMDAwNDcwIHNzIHhv
ciBhbCwweDMwICAgICAgICAgICAgICAgICAqLyAgMHgzNiwgMHgzNCwgMHgzMCwNCisgIC8qIDAw
MDAwNDczIGpzIDB4NGE5ICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3OCwgMHgzNCwNCisg
IC8qIDAwMDAwNDc1IGNtcCBbYngrc2ldLGRoICAgICAgICAgICAgICAgICAqLyAgMHgzOCwgMHgz
MCwNCisgIC8qIDAwMDAwNDc3IGpzIDB4NGFjICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3
OCwgMHgzMywNCisgIC8qIDAwMDAwNDc5IHhvciBjbCxbZGldICAgICAgICAgICAgICAgICAgICAq
LyAgMHgzMiwgMHgwRCwNCisgIC8qIDAwMDAwNDdCIG9yIGFsLFtieCtzaV0gICAgICAgICAgICAg
ICAgICAqLyAgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDdEIGluc3cgICAgICAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2RCwNCisgIC8qIDAwMDAwNDdFIG91dHN3ICAgICAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2RiwNCisgIC8qIDAwMDAwNDdGIGdzIHBvcCBkaSAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2NCwgMHg2NSwgMHg1RiwNCisgIC8qIDAwMDAwNDgyIGNtcCBbYngr
c2ldLGRoICAgICAgICAgICAgICAgICAqLyAgMHgzOCwgMHgzMCwNCisgIC8qIDAwMDAwNDg0IHhv
ciBbYngrc2krMHgzNl0sYmggICAgICAgICAgICAqLyAgMHgzMCwgMHg3OCwgMHgzNiwNCisgIC8q
IDAwMDAwNDg3IHhvciBbYngrc2ldLGRoICAgICAgICAgICAgICAgICAqLyAgMHgzMCwgMHgzMCwN
CisgIC8qIDAwMDAwNDg5IGpzIDB4NGJlICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3OCwg
MHgzMywNCisgIC8qIDAwMDAwNDhCIHhvciBjbCxbZGldICAgICAgICAgICAgICAgICAgICAqLyAg
MHgzMiwgMHgwRCwNCisgIC8qIDAwMDAwNDhEIG9yIGFsLFtieCtzaV0gICAgICAgICAgICAgICAg
ICAqLyAgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNDhGIGluc3cgICAgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg2RCwNCisgIC8qIDAwMDAwNDkwIG91dHN3ICAgICAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg2RiwNCisgIC8qIDAwMDAwNDkxIGdzIHBvcCBkaSAgICAgICAgICAgICAg
ICAgICAgICAqLyAgMHg2NCwgMHg2NSwgMHg1RiwNCisgIC8qIDAwMDAwNDk0IHhvciBbYngrc2ld
LHNpICAgICAgICAgICAgICAgICAqLyAgMHgzMSwgMHgzMCwNCisgIC8qIDAwMDAwNDk2IHhvciBk
aCxbc2ldICAgICAgICAgICAgICAgICAgICAqLyAgMHgzMiwgMHgzNCwNCisgIC8qIDAwMDAwNDk4
IGpzIDB4NGQxICAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3OCwgMHgzNywNCisgIC8qIDAw
MDAwNDlBIGNtcCBbc3M6Yngrc2krMHgzM10sYmggICAgICAgICAqLyAgMHgzNiwgMHgzOCwgMHg3
OCwgMHgzMywNCisgIC8qIDAwMDAwNDlFIHhvciBjbCxbZGldICAgICAgICAgICAgICAgICAgICAq
LyAgMHgzMiwgMHgwRCwNCisgIC8qIDAwMDAwNEEwIG9yIGFsLFtieCtzaV0gICAgICAgICAgICAg
ICAgICAqLyAgMHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNEEyIGluc3cgICAgICAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2RCwNCisgIC8qIDAwMDAwNEEzIG91dHN3ICAgICAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2RiwNCisgIC8qIDAwMDAwNEE0IGdzIHBvcCBkaSAgICAgICAgICAg
ICAgICAgICAgICAqLyAgMHg2NCwgMHg2NSwgMHg1RiwNCisgIC8qIDAwMDAwNEE3IGpueiAweDUx
NyAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NSwgMHg2RSwNCisgIC8qIDAwMDAwNEE5IGpu
eiAweDUxZSAgICAgICAgICAgICAgICAgICAgICAqLyAgMHg3NSwgMHg3MywNCisgIC8qIDAwMDAw
NEFCIGZzIG9yIGF4LDB4YSAgICAgICAgICAgICAgICAgICAqLyAgMHg2NSwgMHg2NCwgMHgwRCwg
MHgwQSwgMHgwMCwNCisgIC8qIDAwMDAwNEIwIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAg
ICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEIyIGFkZCBbYngrc2ldLGFsICAgICAgICAg
ICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEI0IGFkZCBbYngrc2ldLGFsICAg
ICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEI2IGFkZCBbYngrc2ld
LGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEI4IGFkZCBb
Yngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEJB
IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAw
MDAwNEJDIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisg
IC8qIDAwMDAwNEJFIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgw
MCwNCisgIC8qIDAwMDAwNEMwIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgw
MCwgMHgwMCwNCisgIC8qIDAwMDAwNEMyIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAq
LyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEM0IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAg
ICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEM2IGFkZCBbYngrc2ldLGFsICAgICAg
ICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEM4IGFkZCBbYngrc2ldLGFs
ICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNENBIGFkZCBbYngr
c2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNENDIGFk
ZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAw
NENFIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8q
IDAwMDAwNEQwIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwN
CisgIC8qIDAwMDAwNEQyIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwg
MHgwMCwNCisgIC8qIDAwMDAwNEQ0IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAg
MHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEQ2IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAg
ICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEQ4IGFkZCBbYngrc2ldLGFsICAgICAgICAg
ICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNERBIGFkZCBbYngrc2ldLGFsICAg
ICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNERDIGFkZCBbYngrc2ld
LGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNERFIGFkZCBb
Yngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEUw
IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAw
MDAwNEUyIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisg
IC8qIDAwMDAwNEU0IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgw
MCwNCisgIC8qIDAwMDAwNEU2IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgw
MCwgMHgwMCwNCisgIC8qIDAwMDAwNEU4IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAq
LyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEVBIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAg
ICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEVDIGFkZCBbYngrc2ldLGFsICAgICAg
ICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEVFIGFkZCBbYngrc2ldLGFs
ICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEYwIGFkZCBbYngr
c2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEYyIGFk
ZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAw
NEY0IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8q
IDAwMDAwNEY2IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwN
CisgIC8qIDAwMDAwNEY4IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwg
MHgwMCwNCisgIC8qIDAwMDAwNEZBIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAg
MHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEZDIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAg
ICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNEZFIGFkZCBbYngrc2ldLGFsICAgICAgICAg
ICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTAwIGFkZCBbYngrc2ldLGFsICAg
ICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTAyIGFkZCBbYngrc2ld
LGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTA0IGFkZCBb
Yngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTA2
IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAw
MDAwNTA4IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisg
IC8qIDAwMDAwNTBBIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgw
MCwNCisgIC8qIDAwMDAwNTBDIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgw
MCwgMHgwMCwNCisgIC8qIDAwMDAwNTBFIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAq
LyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTEwIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAg
ICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTEyIGFkZCBbYngrc2ldLGFsICAgICAg
ICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTE0IGFkZCBbYngrc2ldLGFs
ICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTE2IGFkZCBbYngr
c2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTE4IGFk
ZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAw
NTFBIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8q
IDAwMDAwNTFDIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwN
CisgIC8qIDAwMDAwNTFFIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwg
MHgwMCwNCisgIC8qIDAwMDAwNTIwIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAg
MHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTIyIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAg
ICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTI0IGFkZCBbYngrc2ldLGFsICAgICAgICAg
ICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTI2IGFkZCBbYngrc2ldLGFsICAg
ICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTI4IGFkZCBbYngrc2ld
LGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTJBIGFkZCBb
Yngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAwMDAwNTJD
IGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisgIC8qIDAw
MDAwNTJFIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgwMCwNCisg
IC8qIDAwMDAwNTMwIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgwMCwgMHgw
MCwNCisgIC8qIDAwMDAwNTMyIGFkZCBbYngrc2ldLGFsICAgICAgICAgICAgICAgICAqLyAgMHgw
MCwgMHgwMCwNCit9Ow0KKyNlbmRpZg0KZGlmZiAtLWdpdCBhL092bWZQa2cvSW50ZWxHdnRHb3BE
eGUvVmJlU2hpbS5zaCBiL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmJlU2hpbS5zaApuZXcgZmls
ZSBtb2RlIDEwMDc1NQppbmRleCAwMDAwMDAwMDAwMDAuLjRmNjFlNTIyMGIwMQotLS0gL2Rldi9u
dWxsCisrKyBiL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmJlU2hpbS5zaApAQCAtMCwwICsxLDgx
IEBACisjIS9iaW4vc2gKKyMjIworIyBAZmlsZQorIyBTaGVsbCBzY3JpcHQgdG8gYXNzZW1ibGUg
YW5kIGR1bXAgdGhlIGZha2UgSW50MTBoIGhhbmRsZXIgZnJvbSBOQVNNIHNvdXJjZSB0bworIyBh
IEMgYXJyYXkuCisjCisjIENvcHlyaWdodCAoQykgMjAyMSwgSW50ZWwgQ29ycG9yYXRpb24uIEFs
bCByaWdodHMgcmVzZXJ2ZWQuPEJSPgorIyBDb3B5cmlnaHQgKEMpIDIwMjAsIFJlYmVjY2EgQ3Jh
biA8cmViZWNjYUBic2Rpby5jb20+CisjIENvcHlyaWdodCAoQykgMjAxNCwgUmVkIEhhdCwgSW5j
LgorIyBDb3B5cmlnaHQgKGMpIDIwMTMgLSAyMDE0LCBJbnRlbCBDb3Jwb3JhdGlvbi4gQWxsIHJp
Z2h0cyByZXNlcnZlZC48QlI+CisjCisjIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBCU0QtMi1D
bGF1c2UtUGF0ZW50CisjCisjIyMKKworc2V0IC1lIC11CisKK1NURU09JChkaXJuYW1lIC0tICIk
MCIpLyQoYmFzZW5hbWUgLS0gIiQwIiAuc2gpCisKKyMKKyMgSW5zdGFsbCBleGl0IGhhbmRsZXIg
LS0gcmVtb3ZlIHRlbXBvcmFyeSBmaWxlcy4KKyMKK2V4aXRfaGFuZGxlcigpCit7CisgIHJtIC1m
IC0tICIkU1RFTSIuYmluICIkU1RFTSIuZGlzYXNtICIkU1RFTSIub2Zmc2V0cyAiJFNURU0iLmlu
c25zIFwKKyAgICAgICIkU1RFTSIuYnl0ZXMKK30KK3RyYXAgZXhpdF9oYW5kbGVyIEVYSVQKKwor
IworIyBBc3NlbWJsZSB0aGUgc291cmNlIGZpbGUuCisjCituYXNtIC1vICIkU1RFTSIuYmluICIk
U1RFTSIuYXNtCisKKyMKKyMgRGlzYXNzZW1ibGUgaXQsIGluIG9yZGVyIHRvIGdldCBhIGJpbmFy
eSBkdW1wIGFzc29jaWF0ZWQgd2l0aCB0aGUgc291cmNlLgorIyAobmRpc2FzbSBkb2Vzbid0IHJl
Y29nbml6ZSB0aGUgIi0tIiBlbmQtb2Ytb3B0aW9ucyBkZWxpbWl0ZXIuKQorIworbmRpc2FzbSAi
JFNURU0iLmJpbiA+IiRTVEVNIi5kaXNhc20KKworIworIyBDcmVhdGUgdGhyZWUgZmlsZXMsIGVh
Y2ggd2l0aCBvbmUgY29sdW1uIG9mIHRoZSBkaXNhc3NlbWJseS4KKyMKKyMgVGhlIGZpcnN0IGNv
bHVtbiBjb250YWlucyB0aGUgb2Zmc2V0cywgYW5kIGl0IHN0YXJ0cyB0aGUgY29tbWVudC4KKyMK
K2N1dCAtYyAxLTggLS0gIiRTVEVNIi5kaXNhc20gXAorfCBzZWQgLWUgJ3MsXiwgIC8qICwnID4i
JFNURU0iLm9mZnNldHMKKworIworIyBUaGUgc2Vjb25kIGNvbHVtbiBjb250YWlucyB0aGUgYXNz
ZW1ibHktbGFuZ3VhZ2UgaW5zdHJ1Y3Rpb25zLCBhbmQgaXQgY2xvc2VzCisjIHRoZSBjb21tZW50
LiBXZSBmaXJzdCBwYWQgaXQgdG8gMzAgY2hhcmFjdGVycy4KKyMKK2N1dCAtYyAyOS0gLS0gIiRT
VEVNIi5kaXNhc20gXAorfCBzZWQgLWUgJ3MsJCwgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAsJyBcCisgICAgICAtZSAncyxeXCguXHszMFx9XCkuKiQsXDEgKi8sJyA+IiRTVEVNIi5pbnNu
cworCisjCisjIFRoZSB0aGlyZCBjb2x1bW4gY29udGFpbnMgdGhlIGJ5dGVzIGNvcnJlc3BvbmRp
bmcgdG8gdGhlIGluc3RydWN0aW9uLAorIyByZXByZXNlbnRlZCBhcyBDIGludGVnZXIgY29uc3Rh
bnRzLiBGaXJzdCBzdHJpcCB0cmFpbGluZyB3aGl0ZXNwYWNlIGZyb20gdGhlCisjIG1pZGRsZSBj
b2x1bW4gb2YgdGhlIGlucHV0IGRpc2Fzc2VtYmx5LCB0aGVuIHByb2Nlc3MgcGFpcnMgb2Ygbmli
Ymxlcy4KKyMKK2N1dCAtYyAxMS0yOCAtLSAiJFNURU0iLmRpc2FzbSBcCit8IHNlZCAtZSAncywg
XCskLCwnIC1lICdzL1woLi5cKS8gMHhcMSwvZycgfCBzZWQgJ3MvMHggICwvL2cnID4iJFNURU0i
LmJ5dGVzCisKKyMKKyMgV3JpdGUgdGhlIG91dHB1dCBmaWxlLCByZWNvbWJpbmluZyB0aGUgY29s
dW1ucy4gVGhlIG91dHB1dCBzaG91bGQgaGF2ZSBDUkxGCisjIGxpbmUgZW5kaW5ncy4KKyMKK3sK
KyAgcHJpbnRmICcvL1xuJworICBwcmludGYgJy8vIFRISVMgRklMRSBXQVMgR0VORVJBVEVEIEJZ
ICIlcyIuIERPIE5PVCBFRElULlxuJyBcCisgICAgICAiJChiYXNlbmFtZSAtLSAiJDAiKSIKKyAg
cHJpbnRmICcvL1xuJworICBwcmludGYgJyNpZm5kZWYgX1ZCRV9TSElNX0hfXG4nCisgIHByaW50
ZiAnI2RlZmluZSBfVkJFX1NISU1fSF9cbicKKyAgcHJpbnRmICdTVEFUSUMgQ09OU1QgVUlOVDgg
Z1ZiZVNoaW1bXSA9IHtcbicKKyAgcGFzdGUgLWQgJyAnIC0tICIkU1RFTSIub2Zmc2V0cyAiJFNU
RU0iLmluc25zICIkU1RFTSIuYnl0ZXMKKyAgcHJpbnRmICd9O1xuJworICBwcmludGYgJyNlbmRp
ZlxuJworfSBcCit8IHVuaXgyZG9zID4iJFNURU0iLmgKZGlmZiAtLWdpdCBhL092bWZQa2cvSW50
ZWxHdnRHb3BEeGUvVmlydHVhbEdwdS5jIGIvT3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9WaXJ0dWFs
R3B1LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5kYzJjMjM3MDZj
OGIKLS0tIC9kZXYvbnVsbAorKysgYi9Pdm1mUGtnL0ludGVsR3Z0R29wRHhlL1ZpcnR1YWxHcHUu
YwpAQCAtMCwwICsxLDQwMCBAQAorLyoqIEBmaWxlDQorICBDb21wb25lbnQgbmFtZSBmb3IgdGhl
IFFFTVUgdmlkZW8gY29udHJvbGxlci4NCisNCisgIENvcHlyaWdodCAoYykgMjAyMSwgSW50ZWwg
Q29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuPEJSPg0KKw0KKyAgU1BEWC1MaWNlbnNl
LUlkZW50aWZpZXI6IEJTRC0yLUNsYXVzZS1QYXRlbnQNCisNCisqKi8NCisNCisjaW5jbHVkZSAi
Q29tbW9uLmgiDQorI2luY2x1ZGUgIlZpcnR1YWxHcHUuaCINCisjaW5jbHVkZSAiR3B1UmVnLmgi
DQorI2luY2x1ZGUgIkd0dC5oIg0KKyNpbmNsdWRlICJEaXNwbGF5LmgiDQorI2luY2x1ZGUgPExp
YnJhcnkvUWVtdUZ3Q2ZnTGliLmg+DQorDQorRUZJX1NUQVRVUw0KK0ludGVsVmlydHVhbEdwdUFj
dGl2ZSAoDQorICBJTiBFRklfUENJX0lPX1BST1RPQ09MICpQY2lJbw0KKyAgKQ0KK3sNCisgIEVG
SV9TVEFUVVMgU3RhdHVzID0gRUZJX1VOU1VQUE9SVEVEOw0KKyAgUENJX1RZUEUwMCBQY2lIZHIg
PSB7MH07DQorICBVSU5UNjQgICAgIE1hZ2ljID0gMDsNCisgIFVJTlQzMiAgICAgVmVyc2lvbiA9
IDA7DQorICBVSU5UMTYgICAgIFZlck1ham9yID0gMCwgVmVyTWlub3IgPSAwOw0KKw0KKyAgR1ZU
X0RFQlVHIChFRklfRF9WRVJCT1NFLCAiJWE6ID4+PlxuIiwgX19GVU5DVElPTl9fKTsNCisNCisg
IFN0YXR1cyA9IFBjaUlvLT5QY2kuUmVhZCAoDQorICAgICAgICAgICAgICAgICAgICAgICAgUGNp
SW8sDQorICAgICAgICAgICAgICAgICAgICAgICAgRWZpUGNpSW9XaWR0aFVpbnQzMiwNCisgICAg
ICAgICAgICAgICAgICAgICAgICAwLA0KKyAgICAgICAgICAgICAgICAgICAgICAgIHNpemVvZiAo
UGNpSGRyKSAvIHNpemVvZiAoVUlOVDMyKSwNCisgICAgICAgICAgICAgICAgICAgICAgICAmUGNp
SGRyDQorICAgICAgICAgICAgICAgICAgICAgICAgKTsNCisgIGlmIChFRklfRVJST1IgKFN0YXR1
cykpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiQ2FuJ3QgcmVhZCBQ
Q0kgY29uZmlnIGhlYWRlciwgc3RhdHVzICVkXG4iLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBT
dGF0dXMgPSBFRklfVU5TVVBQT1JURUQ7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIGlm
ICghSVNfUENJX0RJU1BMQVkgKCZQY2lIZHIpIHx8IFBjaUhkci5IZHIuVmVuZG9ySWQgIT0gMHg4
MDg2KSB7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwNCisgICAgICAiU2tpcCBub24g
SW50ZWwgUENJIERpc3BsYXkgWyUwNHg6JTA0eF0gY2xhc3M6JXhcbiIsDQorICAgICAgUGNpSGRy
Lkhkci5WZW5kb3JJZCwgUGNpSGRyLkhkci5EZXZpY2VJZCwgUGNpSGRyLkhkci5DbGFzc0NvZGVb
Ml0NCisgICAgICApOw0KKyAgICBTdGF0dXMgPSBFRklfVU5TVVBQT1JURUQ7DQorICAgIGdvdG8g
RG9uZTsNCisgIH0NCisNCisgIFN0YXR1cyA9IFBjaUlvLT5NZW0uUmVhZCAoDQorICAgICAgICAg
ICAgICAgICAgICAgICAgUGNpSW8sDQorICAgICAgICAgICAgICAgICAgICAgICAgRWZpUGNpSW9X
aWR0aFVpbnQ2NCwNCisgICAgICAgICAgICAgICAgICAgICAgICBQQ0lfQkFSX0lEWDAsDQorICAg
ICAgICAgICAgICAgICAgICAgICAgdmd0aWZfcmVnKG1hZ2ljKSwNCisgICAgICAgICAgICAgICAg
ICAgICAgICAxLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICZNYWdpYw0KKyAgICAgICAgICAg
ICAgICAgICAgICAgICk7DQorICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgIEdWVF9E
RUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgIkNhbid0IHJlYWQgR1ZUIG1hZ2ljIGZyb20gWyUw
NHg6JTA0eF0sIHN0YXR1cyAlZFxuIiwNCisgICAgICBQY2lIZHIuSGRyLlZlbmRvcklkLCBQY2lI
ZHIuSGRyLkRldmljZUlkLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBTdGF0dXMgPSBFRklfVU5T
VVBQT1JURUQ7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIGlmIChNYWdpYyAhPSBWR1Rf
TUFHSUMpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiUmVhZCBtYWdp
YyBmcm9tIFslMDR4OiUwNHhdLCBnZXQgJXggZXhwZWN0ICV4XG4iLA0KKyAgICAgIFBjaUhkci5I
ZHIuVmVuZG9ySWQsIFBjaUhkci5IZHIuRGV2aWNlSWQsIE1hZ2ljLCBWR1RfTUFHSUMNCisgICAg
ICApOw0KKyAgICBTdGF0dXMgPSBFRklfVU5TVVBQT1JURUQ7DQorICAgIGdvdG8gRG9uZTsNCisg
IH0NCisNCisgIFN0YXR1cyA9IFBjaUlvLT5NZW0uUmVhZCAoDQorICAgICAgICAgICAgICAgICAg
ICAgICAgUGNpSW8sDQorICAgICAgICAgICAgICAgICAgICAgICAgRWZpUGNpSW9XaWR0aFVpbnQz
MiwNCisgICAgICAgICAgICAgICAgICAgICAgICBQQ0lfQkFSX0lEWDAsDQorICAgICAgICAgICAg
ICAgICAgICAgICAgdmd0aWZfcmVnKHZlcnNpb25fbWFqb3IpLA0KKyAgICAgICAgICAgICAgICAg
ICAgICAgIDEsDQorICAgICAgICAgICAgICAgICAgICAgICAgJlZlcnNpb24NCisgICAgICAgICAg
ICAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICBHVlRf
REVCVUcgKEVGSV9EX0VSUk9SLA0KKyAgICAgICJDYW4ndCByZWFkIEdWVCB2ZXJzaW9uIGZyb20g
WyUwNHg6JTA0eF0sIHN0YXR1cyAlZFxuIiwNCisgICAgICBQY2lIZHIuSGRyLlZlbmRvcklkLCBQ
Y2lIZHIuSGRyLkRldmljZUlkLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBTdGF0dXMgPSBFRklf
VU5TVVBQT1JURUQ7DQorICAgIGdvdG8gRG9uZTsNCisgIH0NCisNCisgIFZlck1ham9yID0gVmVy
c2lvbiAmIDB4RkZGRjsNCisgIFZlck1pbm9yID0gKFZlcnNpb24gJiAweEZGRkYpID4+IDE2Ow0K
KyAgaWYgKFZlck1ham9yIDwgVkdUX1ZFUlNJT05fTUFKT1IpIHsNCisgICAgR1ZUX0RFQlVHIChF
RklfRF9FUlJPUiwNCisgICAgICAiQ2hlY2sgVkdUIGludGVyZmFjZSB2ZXJzaW9uIG9mIFslMDR4
OiUwNHhdLCBnb3QgJXguJXgsIGV4cGVjdCAleC4qXG4iLA0KKyAgICAgIFBjaUhkci5IZHIuVmVu
ZG9ySWQsIFBjaUhkci5IZHIuRGV2aWNlSWQsDQorICAgICAgVmVyTWFqb3IsIFZlck1pbm9yLCBW
R1RfVkVSU0lPTl9NQUpPUg0KKyAgICAgICk7DQorICAgIFN0YXR1cyA9IEVGSV9VTlNVUFBPUlRF
RDsNCisgICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9JTkZPLA0K
KyAgICAiSW50ZWwgR1ZULWcgdmlydHVhbCBHUFUgWyUwNHg6JTA0eF0gZGV0ZWN0ZWQsIHZlcnNp
b24gJXguJXhcbiIsDQorICAgIFBjaUhkci5IZHIuVmVuZG9ySWQsIFBjaUhkci5IZHIuRGV2aWNl
SWQsIFZlck1ham9yLCBWZXJNaW5vcg0KKyAgICApOw0KKyAgU3RhdHVzID0gRUZJX1NVQ0NFU1M7
DQorDQorRG9uZToNCisgIEdWVF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA8PDxcbiIsIF9f
RlVOQ1RJT05fXyk7DQorDQorICByZXR1cm4gU3RhdHVzOw0KK30NCisNCitFRklfU1RBVFVTDQor
SW50ZWxWaXJ0dWFsR3B1SW5pdCAoDQorICBJTiBPVVQgR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlBy
aXZhdGUNCisgICkNCit7DQorICBFRklfU1RBVFVTICAgICAgICAgICBTdGF0dXMgPSBFRklfVU5T
VVBQT1JURUQ7DQorICBFRklfUENJX0lPX1BST1RPQ09MICAqUGNpSW87DQorICBQSU5URUxfVklS
VFVBTF9HUFUgICBWaXJ0dWFsR3B1Ow0KKyAgRklSTVdBUkVfQ09ORklHX0lURU0gRndDZmdJdGVt
Ow0KKyAgVUlOVE4gICAgICAgICAgICAgICAgRndDZmdTaXplOw0KKyAgVUlOVDggICAgICAgICAg
ICAgICAgVmFsODsNCisgIFVJTlQ2NCAgICAgICAgICAgICAgIFZhbDY0Ow0KKw0KKyAgR1ZUX0RF
QlVHIChFRklfRF9WRVJCT1NFLCAiJWE6ID4+PlxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIFBj
aUlvID0gUHJpdmF0ZS0+UGNpSW87DQorICBWaXJ0dWFsR3B1ID0gKFBJTlRFTF9WSVJUVUFMX0dQ
VSlQcml2YXRlLT5WaXJ0dWFsR3B1Ow0KKyAgU3RhdHVzID0gUGNpSW8tPlBjaS5SZWFkICgNCisg
ICAgICAgICAgICAgICAgICAgICAgICBQY2lJbywNCisgICAgICAgICAgICAgICAgICAgICAgICBF
ZmlQY2lJb1dpZHRoVWludDE2LA0KKyAgICAgICAgICAgICAgICAgICAgICAgIFBDSV9WRU5ET1Jf
SURfT0ZGU0VULA0KKyAgICAgICAgICAgICAgICAgICAgICAgIDEsDQorICAgICAgICAgICAgICAg
ICAgICAgICAgJlZpcnR1YWxHcHUtPlZlbmRvcklkDQorICAgICAgICAgICAgICAgICAgICAgICAg
KTsNCisgIGlmIChFRklfRVJST1IgKFN0YXR1cykpIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9F
UlJPUiwNCisgICAgICAiQ2FuJ3QgcmVhZCBQQ0lfVkVORE9SX0lEX09GRlNFVCwgc3RhdHVzICVk
XG4iLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBnb3RvIERvbmU7DQorICB9DQorDQorICBTdGF0
dXMgPSBQY2lJby0+UGNpLlJlYWQgKA0KKyAgICAgICAgICAgICAgICAgICAgICAgIFBjaUlvLA0K
KyAgICAgICAgICAgICAgICAgICAgICAgIEVmaVBjaUlvV2lkdGhVaW50MTYsDQorICAgICAgICAg
ICAgICAgICAgICAgICAgUENJX0RFVklDRV9JRF9PRkZTRVQsDQorICAgICAgICAgICAgICAgICAg
ICAgICAgMSwNCisgICAgICAgICAgICAgICAgICAgICAgICAmVmlydHVhbEdwdS0+RGV2aWNlSWQN
CisgICAgICAgICAgICAgICAgICAgICAgICApOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkg
ew0KKyAgICBHVlRfREVCVUcgKEVGSV9EX0VSUk9SLA0KKyAgICAgICJDYW4ndCByZWFkIFBDSV9E
RVZJQ0VfSURfT0ZGU0VULCBzdGF0dXMgJWRcbiIsIFN0YXR1cw0KKyAgICAgICk7DQorICAgIGdv
dG8gRG9uZTsNCisgIH0NCisNCisgIFN0YXR1cyA9IFBjaUlvLT5QY2kuUmVhZCAoDQorICAgICAg
ICAgICAgICAgICAgICAgICAgUGNpSW8sDQorICAgICAgICAgICAgICAgICAgICAgICAgRWZpUGNp
SW9XaWR0aFVpbnQ2NCwNCisgICAgICAgICAgICAgICAgICAgICAgICBQQ0lfQkFTRV9BRERSRVNT
UkVHX09GRlNFVCArIFBDSV9CQVJfSURYMiAqIDQsDQorICAgICAgICAgICAgICAgICAgICAgICAg
MSwNCisgICAgICAgICAgICAgICAgICAgICAgICAmVmFsNjQNCisgICAgICAgICAgICAgICAgICAg
ICAgICApOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICBHVlRfREVCVUcgKEVG
SV9EX0VSUk9SLCAiQ2FuJ3QgZ2V0IEdNQURSIGZyb20gQkFSMiwgc3RhdHVzICVkXG4iLCBTdGF0
dXMpOw0KKyAgICBnb3RvIERvbmU7DQorICB9DQorDQorICBpZiAoVmFsNjQgJiAweDEpIHsNCisg
ICAgU3RhdHVzID0gRUZJX09VVF9PRl9SRVNPVVJDRVM7DQorICAgIEdWVF9ERUJVRyAoRUZJX0Rf
RVJST1IsICJCQVIyIGlzbid0IG1lbW9yeSBzcGFjZSwgc3RhdHVzICVkXG4iLCBTdGF0dXMpOw0K
KyAgICBnb3RvIERvbmU7DQorICB9DQorDQorICBzd2l0Y2ggKFZhbDY0ID4+IDEgJiAweDMpIHsN
CisgIGNhc2UgMDoNCisgICAgVmlydHVhbEdwdS0+R3B1TWVtQWRkciA9IFZhbDY0ICYgMHhGRkZG
RkZGMDsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLCAiQkFSMiBoYXMgMzItYml0IGFj
Y2VzcyBzcGFjZVxuIik7DQorICAgIGJyZWFrOw0KKyAgY2FzZSAyOg0KKyAgICBWaXJ0dWFsR3B1
LT5HcHVNZW1BZGRyID0gVmFsNjQgJiB+MHhGOw0KKyAgICBHVlRfREVCVUcgKEVGSV9EX1ZFUkJP
U0UsICJCQVIyIGhhcyA2NC1iaXQgYWNjZXNzIHNwYWNlXG4iKTsNCisgICAgYnJlYWs7DQorICBk
ZWZhdWx0Og0KKyAgICBTdGF0dXMgPSBFRklfT1VUX09GX1JFU09VUkNFUzsNCisgICAgR1ZUX0RF
QlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiQkFSMiBoYXMgdW5rbm93biBhY2Nlc3Mgc3BhY2Us
IHN0YXR1cyAlZFxuIiwgU3RhdHVzDQorICAgICAgKTsNCisgICAgZ290byBEb25lOw0KKyAgICBi
cmVhazsNCisgIH0NCisNCisgIFN0YXR1cyA9IFBjaUlvLT5QY2kuUmVhZCAoDQorICAgICAgICAg
ICAgICAgICAgICAgICAgUGNpSW8sDQorICAgICAgICAgICAgICAgICAgICAgICAgRWZpUGNpSW9X
aWR0aFVpbnQ4LA0KKyAgICAgICAgICAgICAgICAgICAgICAgIFBDSV9SRUdfTVNBQywNCisgICAg
ICAgICAgICAgICAgICAgICAgICAxLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICZWYWw4DQor
ICAgICAgICAgICAgICAgICAgICAgICAgKTsNCisgIGlmIChFRklfRVJST1IgKFN0YXR1cykpIHsN
CisgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJPUiwNCisgICAgICAiQ2FuJ3QgZ2V0IE1TQUMgZnJv
bSAleCwgc3RhdHVzICVkXG4iLCBQQ0lfUkVHX01TQUMsIFN0YXR1cw0KKyAgICAgICk7DQorICAg
IGdvdG8gRG9uZTsNCisgIH0NCisNCisgIFZhbDggJj0gMHgxRjsNCisgIGlmIChWYWw4ICYgMHgx
MCkgew0KKyAgICBWaXJ0dWFsR3B1LT5HcHVNZW1TaXplTSA9IDQwOTY7DQorICB9IGVsc2Ugew0K
KyAgICBWYWw4ICY9IDB4RjsNCisgICAgaWYgKFZhbDggJiAweDgpIHsNCisgICAgICBWaXJ0dWFs
R3B1LT5HcHVNZW1TaXplTSA9IDIwNDg7DQorICAgIH0gZWxzZSB7DQorICAgICAgVmFsOCAmPSAw
eDc7DQorICAgICAgaWYgKFZhbDggJiAweDQpIHsNCisgICAgICAgIFZpcnR1YWxHcHUtPkdwdU1l
bVNpemVNID0gMTAyNDsNCisgICAgICB9IGVsc2Ugew0KKyAgICAgICAgVmFsOCAmPSAweDM7DQor
ICAgICAgICBpZiAoVmFsOCAmIDB4Mikgew0KKyAgICAgICAgICBWaXJ0dWFsR3B1LT5HcHVNZW1T
aXplTSA9IDUxMjsNCisgICAgICAgIH0gZWxzZSB7DQorICAgICAgICAgIGlmIChWYWw4ICYgMHgx
KSB7DQorICAgICAgICAgICAgVmlydHVhbEdwdS0+R3B1TWVtU2l6ZU0gPSAyNTY7DQorICAgICAg
ICAgIH0gZWxzZSB7DQorICAgICAgICAgICAgVmlydHVhbEdwdS0+R3B1TWVtU2l6ZU0gPSAxMjg7
DQorICAgICAgICAgIH0NCisgICAgICAgIH0NCisgICAgICB9DQorICAgIH0NCisgIH0NCisNCisg
IFN0YXR1cyA9IFFlbXVGd0NmZ0ZpbmRGaWxlICgiZXRjL2lnZC1vcHJlZ2lvbiIsICZGd0NmZ0l0
ZW0sICZGd0NmZ1NpemUpOw0KKyAgaWYgKFN0YXR1cyA9PSBFRklfU1VDQ0VTUyAmJiBGd0NmZ1Np
emUgPT0gT1BSRUdJT05fU0laRSkgew0KKyAgICAvLyBPcFJlZ2lvbiBtdXN0IHNpdCBiZWxvdyA0
IEdCDQorICAgIFZpcnR1YWxHcHUtPk9wUmVnaW9uID0gU0laRV80R0IgLSAxOw0KKyAgICBTdGF0
dXMgPSBnQlMtPkFsbG9jYXRlUGFnZXMgKA0KKyAgICAgICAgICAgICAgICBBbGxvY2F0ZU1heEFk
ZHJlc3MsDQorICAgICAgICAgICAgICAgIEVmaVJlc2VydmVkTWVtb3J5VHlwZSwNCisgICAgICAg
ICAgICAgICAgRUZJX1NJWkVfVE9fUEFHRVMgKE9QUkVHSU9OX1NJWkUpLA0KKyAgICAgICAgICAg
ICAgICAmVmlydHVhbEdwdS0+T3BSZWdpb24NCisgICAgICAgICAgICAgICAgKTsNCisgICAgaWYg
KEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQor
ICAgICAgICAiRmFpbCB0byBhbGxvY2F0ZSAlZCBwYWdlcyBzaXplICVseCBmb3IgT3BSZWdpb24s
IHN0YXR1cyAlZFxuIiwNCisgICAgICAgIEVGSV9TSVpFX1RPX1BBR0VTIChPUFJFR0lPTl9TSVpF
KSwgT1BSRUdJT05fU0laRSwgU3RhdHVzDQorICAgICAgICApOw0KKyAgICAgIGdvdG8gRG9uZTsN
CisgICAgfQ0KKyAgICBRZW11RndDZmdTZWxlY3RJdGVtIChGd0NmZ0l0ZW0pOw0KKyAgICBRZW11
RndDZmdSZWFkQnl0ZXMgKEZ3Q2ZnU2l6ZSwgKFZPSUQqKVZpcnR1YWxHcHUtPk9wUmVnaW9uKTsN
CisgICAgU3RhdHVzID0gUGNpSW8tPlBjaS5Xcml0ZSAoDQorICAgICAgICAgICAgICAgICAgICAg
ICAgICBQY2lJbywNCisgICAgICAgICAgICAgICAgICAgICAgICAgIEVmaVBjaUlvV2lkdGhVaW50
MzIsDQorICAgICAgICAgICAgICAgICAgICAgICAgICBQQ0lfUkVHX0FTTFMsDQorICAgICAgICAg
ICAgICAgICAgICAgICAgICAxLA0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgKFVJTlQzMiop
JlZpcnR1YWxHcHUtPk9wUmVnaW9uDQorICAgICAgICAgICAgICAgICAgICAgICAgICApOw0KKyAg
ICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgICAgR1ZUX0RFQlVHIChFRklfRF9FUlJP
UiwNCisgICAgICAgICJGYWlsIHRvIHdyaXRlIE9wUmVnaW9uICVwIHRvIFBDSSBjb25maWcgb2Zm
c2V0IDB4JXgsIHN0YXR1cyAlZFxuIiwNCisgICAgICAgIFZpcnR1YWxHcHUtPk9wUmVnaW9uLCBQ
Q0lfUkVHX0FTTFMsIFN0YXR1cw0KKyAgICAgICAgKTsNCisgICAgICBnb3RvIERvbmU7DQorICAg
IH0gZWxzZSB7DQorICAgICAgR1ZUX0RFQlVHIChFRklfRF9JTkZPLA0KKyAgICAgICAgIk9wUmVn
aW9uICVwIGlzIHNldCB0byBQQ0kgY29uZmlnIG9mZnNldCAweCV4XG4iLA0KKyAgICAgICAgVmly
dHVhbEdwdS0+T3BSZWdpb24sIFBDSV9SRUdfQVNMUw0KKyAgICAgICAgKTsNCisgICAgfQ0KKyAg
fSBlbHNlIHsNCisgICAgR1ZUX0RFQlVHIChFRklfRF9WRVJCT1NFLA0KKyAgICAgICJOb3QgaWdk
LW9wcmVnaW9uIGZvdW5kIGluIFFFTVUgZmlybXdhcmUgY29uZmlnXG4iDQorICAgICAgKTsNCisg
IH0NCisNCisgIFJlZ1JlYWQzMiAoUHJpdmF0ZSwNCisgICAgdmd0aWZfcmVnKGF2YWlsX3JzLm1h
cHBhYmxlX2dtYWRyLmJhc2UpLCAmVmlydHVhbEdwdS0+VmlzaWJsZU9mZnNldCk7DQorICBSZWdS
ZWFkMzIgKFByaXZhdGUsDQorICAgIHZndGlmX3JlZyhhdmFpbF9ycy5tYXBwYWJsZV9nbWFkci5z
aXplKSwgJlZpcnR1YWxHcHUtPlZpc2libGVTaXplKTsNCisgIFJlZ1JlYWQzMiAoUHJpdmF0ZSwN
CisgICAgdmd0aWZfcmVnKGF2YWlsX3JzLm5vbm1hcHBhYmxlX2dtYWRyLmJhc2UpLCAmVmlydHVh
bEdwdS0+SW52aXNpYmxlT2Zmc2V0KTsNCisgIFJlZ1JlYWQzMiAoUHJpdmF0ZSwNCisgICAgdmd0
aWZfcmVnKGF2YWlsX3JzLm5vbm1hcHBhYmxlX2dtYWRyLnNpemUpLCAmVmlydHVhbEdwdS0+SW52
aXNpYmxlU2l6ZSk7DQorICBWaXJ0dWFsR3B1LT5WaXNpYmxlR0dUVE9mZnNldCA9IFZpcnR1YWxH
cHUtPlZpc2libGVPZmZzZXQgPj4gR1RUX1BBR0VfU0hJRlQ7DQorICBWaXJ0dWFsR3B1LT5WaXNp
YmxlR0dUVFNpemUgPSBWaXJ0dWFsR3B1LT5WaXNpYmxlU2l6ZSA+PiBHVFRfUEFHRV9TSElGVDsN
CisgIFZpcnR1YWxHcHUtPkludmlzaWJsZUdHVFRPZmZzZXQgPSBWaXJ0dWFsR3B1LT5JbnZpc2li
bGVPZmZzZXQgPj4gR1RUX1BBR0VfU0hJRlQ7DQorICBWaXJ0dWFsR3B1LT5JbnZpc2libGVHR1RU
U2l6ZSA9IFZpcnR1YWxHcHUtPkludmlzaWJsZVNpemUgPj4gR1RUX1BBR0VfU0hJRlQ7DQorDQor
ICBHVlRfREVCVUcgKA0KKyAgICBFRklfRF9JTkZPLA0KKyAgICAiR01BRFIgWzB4JWx4IC0gMHgl
bHhdLCBzaXplICVkIE1CXG4iLA0KKyAgICBWaXJ0dWFsR3B1LT5HcHVNZW1BZGRyLA0KKyAgICBW
aXJ0dWFsR3B1LT5HcHVNZW1BZGRyICsgVmlydHVhbEdwdS0+R3B1TWVtU2l6ZU0gKiAweDEwMDAw
MCwNCisgICAgVmlydHVhbEdwdS0+R3B1TWVtU2l6ZU0NCisgICAgKTsNCisgIEdWVF9ERUJVRyAo
DQorICAgIEVGSV9EX0lORk8sDQorICAgICJ2aXNpYmxlIG9mZnNldCBbMHgleCAtIDB4JXhdIHNp
emUgJWQgS0IsIEdHVFQgcmFuZ2UgWyV4IC0gJXhdXG4iLA0KKyAgICBWaXJ0dWFsR3B1LT5WaXNp
YmxlT2Zmc2V0LA0KKyAgICBWaXJ0dWFsR3B1LT5WaXNpYmxlT2Zmc2V0ICsgVmlydHVhbEdwdS0+
VmlzaWJsZVNpemUsDQorICAgIFZpcnR1YWxHcHUtPlZpc2libGVTaXplIC8gMHg0MDAsDQorICAg
IFZpcnR1YWxHcHUtPlZpc2libGVHR1RUT2Zmc2V0LA0KKyAgICBWaXJ0dWFsR3B1LT5WaXNpYmxl
R0dUVE9mZnNldCArIFZpcnR1YWxHcHUtPlZpc2libGVHR1RUU2l6ZQ0KKyAgICApOw0KKyAgR1ZU
X0RFQlVHICgNCisgICAgRUZJX0RfSU5GTywNCisgICAgImludmlzaWJsZSBvZmZzZXQgWzB4JXgg
LSAweCV4XSBzaXplICVkIEtCLCBHR1RUIHJhbmdlIFsleCAtICV4XVxuIiwNCisgICAgVmlydHVh
bEdwdS0+SW52aXNpYmxlT2Zmc2V0LA0KKyAgICBWaXJ0dWFsR3B1LT5JbnZpc2libGVPZmZzZXQg
KyBWaXJ0dWFsR3B1LT5JbnZpc2libGVTaXplLA0KKyAgICBWaXJ0dWFsR3B1LT5JbnZpc2libGVT
aXplIC8gMHg0MDAsDQorICAgIFZpcnR1YWxHcHUtPkludmlzaWJsZUdHVFRPZmZzZXQsDQorICAg
IFZpcnR1YWxHcHUtPkludmlzaWJsZUdHVFRPZmZzZXQgKyBWaXJ0dWFsR3B1LT5JbnZpc2libGVH
R1RUU2l6ZQ0KKyAgICApOw0KKw0KKyAgU3RhdHVzID0gSW50ZWxWaXJ0dWFsR3B1RGlzcGxheUlu
aXQgKFByaXZhdGUpOw0KKyAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0KKyAgICBHVlRfREVC
VUcgKEVGSV9EX0VSUk9SLA0KKyAgICAgICJGYWlsIHRvIGluaXRpYWxpemUgZGlzcGxheSwgc3Rh
dHVzICVkXG4iLCBTdGF0dXMNCisgICAgICApOw0KKyAgICBnb3RvIERvbmU7DQorICB9DQorDQor
ICBTdGF0dXMgPSBJbnRlbFZpcnR1YWxHcHVTZXRNb2RlICgmUHJpdmF0ZS0+R3JhcGhpY3NPdXRw
dXRQcm90b2NvbCwgMCk7DQorICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgIEdWVF9E
RUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgIkZhaWwgdG8gc2V0IGluaXQgZGlzcGxheSBtb2Rl
LCBzdGF0dXMgJWRcbiIsIFN0YXR1cw0KKyAgICAgICk7DQorICAgIGdvdG8gRG9uZTsNCisgIH0N
CisNCisgIFN0YXR1cyA9IEludGVsVmlydHVhbEdwdU5vdGlmeURpc3BsYXlSZWFkeSAoUHJpdmF0
ZSwgVFJVRSk7DQorICBpZiAoRUZJX0VSUk9SIChTdGF0dXMpKSB7DQorICAgIEdWVF9ERUJVRyAo
RUZJX0RfRVJST1IsDQorICAgICAgIkZhaWwgdG8gbm90aWZ5IGRpc3BsYXkgcmVhZHksIHN0YXR1
cyAlZFxuIiwgU3RhdHVzDQorICAgICAgKTsNCisgICAgZ290byBEb25lOw0KKyAgfQ0KKw0KKyAg
Ly8gRmx1c2ggYWxsIHJlZyBhZnRlciBEaXNwbGF5UmVhZHkNCisgIFN0YXR1cyA9IEludGVsVmly
dHVhbEdwdUVuYWJsZURpc3BsYXkgKA0KKyAgICAgICAgICAgICBQcml2YXRlLA0KKyAgICAgICAg
ICAgICAwLA0KKyAgICAgICAgICAgICBUUlVFDQorICAgICAgICAgICAgICk7DQorDQorRG9uZToN
CisNCisgIEdWVF9ERUJVRyAoRUZJX0RfVkVSQk9TRSwgIiVhOiA8PDxcbiIsIF9fRlVOQ1RJT05f
Xyk7DQorDQorICByZXR1cm4gU3RhdHVzOw0KK30NCisNCitFRklfU1RBVFVTDQorSW50ZWxWaXJ0
dWFsR3B1Q2xlYW4gKA0KKyAgSU4gT1VUIEdWVF9HT1BfUFJJVkFURV9EQVRBICpQcml2YXRlDQor
ICApDQorew0KKyAgRUZJX1NUQVRVUyAgICAgICAgIFN0YXR1cyA9IEVGSV9JTlZBTElEX1BBUkFN
RVRFUjsNCisgIFBJTlRFTF9WSVJUVUFMX0dQVSBWaXJ0dWFsR3B1Ow0KKw0KKyAgR1ZUX0RFQlVH
IChFRklfRF9WRVJCT1NFLCAiJWE6ID4+PlxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIFN0YXR1
cyA9IEludGVsVmlydHVhbEdwdURpc3BsYXlDbGVhbiAoUHJpdmF0ZSk7DQorICBpZiAoRUZJX0VS
Uk9SIChTdGF0dXMpKSB7DQorICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsICJGYWlsIHRvIGNs
ZWFuIGRpc3BsYXksIHN0YXR1cyAlZFxuIiwgU3RhdHVzKTsNCisgICAgZ290byBEb25lOw0KKyAg
fQ0KKw0KKyAgVmlydHVhbEdwdSA9IChQSU5URUxfVklSVFVBTF9HUFUpUHJpdmF0ZS0+VmlydHVh
bEdwdTsNCisgIGlmIChWaXJ0dWFsR3B1LT5PcFJlZ2lvbikgew0KKyAgICBTdGF0dXMgPSBnQlMt
PkZyZWVQYWdlcyAoDQorICAgICAgICAgICAgICAgICAgICBWaXJ0dWFsR3B1LT5PcFJlZ2lvbiwN
CisgICAgICAgICAgICAgICAgICAgIEVGSV9TSVpFX1RPX1BBR0VTIChPUFJFR0lPTl9TSVpFKQ0K
KyAgICAgICAgICAgICAgICAgICAgKTsNCisgICAgaWYgKEVGSV9FUlJPUiAoU3RhdHVzKSkgew0K
KyAgICAgIEdWVF9ERUJVRyAoRUZJX0RfRVJST1IsDQorICAgICAgICAiRnJlZVBhZ2VzIGZhaWxl
ZCBmb3IgT3BSZWdpb24sIHBhZ2VzICVkLCBzaXplICVkLCBzdGF0dXMgJWRcbiIsDQorICAgICAg
ICBFRklfU0laRV9UT19QQUdFUyAoT1BSRUdJT05fU0laRSksIE9QUkVHSU9OX1NJWkUsIFN0YXR1
cw0KKyAgICAgICAgKTsNCisgICAgICAgIGdvdG8gRG9uZTsNCisgICAgfQ0KKyAgICBTdGF0dXMg
PSBFRklfU1VDQ0VTUzsNCisgIH0NCisNCitEb25lOg0KKw0KKyAgR1ZUX0RFQlVHIChFRklfRF9W
RVJCT1NFLCAiJWE6IDw8PFxuIiwgX19GVU5DVElPTl9fKTsNCisNCisgIHJldHVybiBTdGF0dXM7
DQorfQ0KZGlmZiAtLWdpdCBhL092bWZQa2cvSW50ZWxHdnRHb3BEeGUvVmlydHVhbEdwdS5oIGIv
T3ZtZlBrZy9JbnRlbEd2dEdvcER4ZS9WaXJ0dWFsR3B1LmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQK
aW5kZXggMDAwMDAwMDAwMDAwLi42MGQ4MGVhZGIzYWMKLS0tIC9kZXYvbnVsbAorKysgYi9Pdm1m
UGtnL0ludGVsR3Z0R29wRHhlL1ZpcnR1YWxHcHUuaApAQCAtMCwwICsxLDUyIEBACisvKiogQGZp
bGUNCisgIENvbXBvbmVudCBuYW1lIGZvciB0aGUgUUVNVSB2aWRlbyBjb250cm9sbGVyLg0KKw0K
KyAgQ29weXJpZ2h0IChjKSAyMDIxLCBJbnRlbCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNl
cnZlZC48QlI+DQorDQorICBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTItQ2xhdXNlLVBh
dGVudA0KKw0KKyoqLw0KKw0KKyNpZm5kZWYgX19WSVJUVUFMR1BVX0hfDQorI2RlZmluZSBfX1ZJ
UlRVQUxHUFVfSF8NCisNCisjaW5jbHVkZSA8RGlzcGxheS5oPg0KKw0KKyNkZWZpbmUgUENJX1JF
R19NU0FDIDB4NjINCisjZGVmaW5lIFBDSV9SRUdfQVNMUyAweEZDDQorDQorI2RlZmluZSBPUFJF
R0lPTl9TSVpFIFNJWkVfOEtCDQorDQordHlwZWRlZiBzdHJ1Y3QgX0lOVEVMX1ZJUlRVQUxfR1BV
IHsNCisgIFVJTlQxNiAgICAgICAgICAgICAgICAgICAgVmVuZG9ySWQ7DQorICBVSU5UMTYgICAg
ICAgICAgICAgICAgICAgIERldmljZUlkOw0KKyAgRUZJX1BIWVNJQ0FMX0FERFJFU1MgICAgICBP
cFJlZ2lvbjsNCisgIEVGSV9QSFlTSUNBTF9BRERSRVNTICAgICAgR3B1TWVtQWRkcjsNCisgIFVJ
TlQzMiAgICAgICAgICAgICAgICAgICAgR3B1TWVtU2l6ZU07DQorICBVSU5UMzIgICAgICAgICAg
ICAgICAgICAgIFZpc2libGVPZmZzZXQ7DQorICBVSU5UMzIgICAgICAgICAgICAgICAgICAgIFZp
c2libGVTaXplOw0KKyAgVUlOVDMyICAgICAgICAgICAgICAgICAgICBWaXNpYmxlR0dUVE9mZnNl
dDsNCisgIFVJTlQzMiAgICAgICAgICAgICAgICAgICAgVmlzaWJsZUdHVFRTaXplOw0KKyAgVUlO
VDMyICAgICAgICAgICAgICAgICAgICBJbnZpc2libGVPZmZzZXQ7DQorICBVSU5UMzIgICAgICAg
ICAgICAgICAgICAgIEludmlzaWJsZVNpemU7DQorICBVSU5UMzIgICAgICAgICAgICAgICAgICAg
IEludmlzaWJsZUdHVFRPZmZzZXQ7DQorICBVSU5UMzIgICAgICAgICAgICAgICAgICAgIEludmlz
aWJsZUdHVFRTaXplOw0KKyAgSU5URUxfVklSVFVBTF9HUFVfRElTUExBWSBEaXNwbGF5Ow0KK30g
SU5URUxfVklSVFVBTF9HUFUsICpQSU5URUxfVklSVFVBTF9HUFU7DQorDQorRUZJX1NUQVRVUw0K
K0ludGVsVmlydHVhbEdwdUFjdGl2ZSAoDQorICBJTiBFRklfUENJX0lPX1BST1RPQ09MICpQY2lJ
bw0KKyAgKTsNCisNCitFRklfU1RBVFVTDQorSW50ZWxWaXJ0dWFsR3B1SW5pdCAoDQorICBJTiBP
VVQgR1ZUX0dPUF9QUklWQVRFX0RBVEEgKlByaXZhdGUNCisgICk7DQorDQorRUZJX1NUQVRVUw0K
K0ludGVsVmlydHVhbEdwdUNsZWFuICgNCisgIElOIE9VVCBHVlRfR09QX1BSSVZBVEVfREFUQSAq
UHJpdmF0ZQ0KKyAgKTsNCisNCisjZW5kaWYgLy9fX1ZJUlRVQUxHUFVfSF8NCi0tIAoyLjMwLjEK
Cg==


Laszlo Ersek
 

Adding Gerd and Alex; some comments below (near the end of the patch --
keeping full context for Gerd's and Alex's sake):

On 03/05/21 07:20, Colin Xu wrote:
Intel GVT-g GOP DXE supports OVMF GOP output its frame buffer to vGPU
partitioned aperture mapped by GGTT, so that the GOP output can be
mediated to its backend for display (i.e. QEMU GTK display via dma-buf).

Unlike ACRN GVT-d integrating native GOP/VBT into it's OVMF, the GVT-g
GOP is an open-source implementation which follows Intel GVT-g framework
to interact with KVMGT in host kernel so that the GOP frame buffer
content can be processed properly.

With GVT-g GOP enabled OVMF, guest VM can output its framebuffer
content to KVMGT via GOP, with a proper backend support (i.e. QEMU GTK
display with dma-buf), the following content is now directly visible to
user unlike previosly need a second GPU:
- OVMF EFI Shell
- Bootloader (i.e. grub)
- OS installation progress. (before built-in GFX driver loaded)
- Pre GFX Driver display (i.e. Android/Linux boot splash or logo,
Windows 8.1 boot progress/safe mode/recovery mode/BSOD/GPU-disabled
desktop, etc.)

GVT-g GOP has below capabilites:
- Check GVT-g compatibility via PV info, only enable GVT-g GOP when it's
compatible with KVMGT.
- R/W MMIO from BAR0.
- R/W Global GTT from BAR0.
- Reserve and program OpRegion address at ASLS location so that guest
driver can decode GVT-g simluated VBT and enabled display properly.
- Reserve guest memory and map to BAR2 partitioned range with proper
GGTT, so that KVMGT can access via proper guest GTT to host GGTT map.
- All supported EFI_GRAPHICS_OUTPUT_BLT_OPERATION from/to video memory.
- Enable/disable GOP content on PIPE_A, PLANE_PRIMARY with proper scaling.
- VBE Shim so that some OS can query non-empty mode info via INT10 call
to enable the desktop when GPU is disabled.

V2:
Program PIPESRC to match active H/V.

Signed-off-by: Colin Xu <colin.xu@intel.com>
---
OvmfPkg/IntelGvtGopDxe/Common.h | 45 +
OvmfPkg/IntelGvtGopDxe/DebugHelper.h | 20 +
OvmfPkg/IntelGvtGopDxe/Display.c | 1077 +++++++++++++++++++++
OvmfPkg/IntelGvtGopDxe/Display.h | 141 +++
OvmfPkg/IntelGvtGopDxe/GopDriver.c | 478 +++++++++
OvmfPkg/IntelGvtGopDxe/GpuReg.c | 91 ++
OvmfPkg/IntelGvtGopDxe/GpuReg.h | 175 ++++
OvmfPkg/IntelGvtGopDxe/Gtt.c | 162 ++++
OvmfPkg/IntelGvtGopDxe/Gtt.h | 51 +
OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf | 59 ++
OvmfPkg/IntelGvtGopDxe/VbeShim.asm | 343 +++++++
OvmfPkg/IntelGvtGopDxe/VbeShim.c | 258 +++++
OvmfPkg/IntelGvtGopDxe/VbeShim.h | 912 +++++++++++++++++
OvmfPkg/IntelGvtGopDxe/VbeShim.sh | 81 ++
OvmfPkg/IntelGvtGopDxe/VirtualGpu.c | 400 ++++++++
OvmfPkg/IntelGvtGopDxe/VirtualGpu.h | 52 +
16 files changed, 4345 insertions(+)
create mode 100644 OvmfPkg/IntelGvtGopDxe/Common.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/DebugHelper.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/Display.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/Display.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/GopDriver.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/GpuReg.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/GpuReg.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/Gtt.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/Gtt.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf
create mode 100644 OvmfPkg/IntelGvtGopDxe/VbeShim.asm
create mode 100644 OvmfPkg/IntelGvtGopDxe/VbeShim.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/VbeShim.h
create mode 100755 OvmfPkg/IntelGvtGopDxe/VbeShim.sh
create mode 100644 OvmfPkg/IntelGvtGopDxe/VirtualGpu.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/VirtualGpu.h

diff --git a/OvmfPkg/IntelGvtGopDxe/Common.h b/OvmfPkg/IntelGvtGopDxe/Common.h
new file mode 100644
index 000000000000..cf30752eb8f3
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Common.h
@@ -0,0 +1,45 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __COMMON_H_
+
+#include <Protocol/PciIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/GraphicsOutput.h>
+
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include "DebugHelper.h"
+
+#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
+
+typedef struct {
+ UINT64 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 OriginalPciAttr;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutputProtocol;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevPath;
+ VOID *VirtualGpu;
+} GVT_GOP_PRIVATE_DATA;
+
+#define GVT_GOP_MAGIC SIGNATURE_64('G','V','T','G','V','G','O','P')
+#define GVT_GOP_PRIVATE_DATA_FROM_THIS(a) CR(a, GVT_GOP_PRIVATE_DATA, GraphicsOutputProtocol, GVT_GOP_MAGIC)
+
+#define __COMMON_H_
+#endif //__COMMON_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/DebugHelper.h b/OvmfPkg/IntelGvtGopDxe/DebugHelper.h
new file mode 100644
index 000000000000..75158d713ec3
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/DebugHelper.h
@@ -0,0 +1,20 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __DEBUGHELPER_H_
+#define __DEBUGHELPER_H_
+
+#include <Library/DebugLib.h>
+
+#define GVT_DEBUG(ErrLevel, Fmt, Args...) \
+ do { \
+ DEBUG ((ErrLevel, "GvtGop: "Fmt, ##Args));\
+ } while (FALSE)
+
+#endif //__DEBUGHELPER_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/Display.c b/OvmfPkg/IntelGvtGopDxe/Display.c
new file mode 100644
index 000000000000..133de25ff03c
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Display.c
@@ -0,0 +1,1077 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "Display.h"
+#include "GpuReg.h"
+#include "Gtt.h"
+#include "VirtualGpu.h"
+
+EFI_STATUS
+IntelVirtualGpuDisplayInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+ UINT32 Val32;
+ UINTN Width, Height, ModeNumber;
+ EFI_TPL OriginalTPL;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ /*
+ * If PcdVideoHorizontalResolution or PcdVideoVerticalResolution is not set,
+ * GOP will query the mode list reported to find the highest resolution.
+ * Otherwise, check if the set PcdVideo*Resolution is defined.
+ * If not supported, try 800x600 which is required by UEFI/EFI spec.
+ * If still not supported, use the 1st mode in mode list.
+ * If there are multiple video devices, graphic console driver will set all
+ * the video devices to the same mode.
+ * According to UEFI/EFI spec, in addition to platform design guide, on-board
+ * graphics should support native mode of the display, plug-in graphics
+ * should support 800x600x32 or 640x480x32.
+ * According to some OS requirement (i.e. UEFI requirment for Windows 10),
+ * integrated displays should support panel native resolution and external
+ * displays should support the maximum resolution of both GPU and display in
+ * GOP. For alternate display output, it should support native or highest
+ * compatible resolution, otherwise support an known mode to be compatible
+ * with as many monitors as possible (640x480, 1024x768).
+ * Due to above requirement, use native resolution if PcdVideo*Resolution is
+ * not defined. To reduce GGTT write overhead, also limit the maximum to
+ * DISPLAY_WIDTH_MAX/DISPLAY_HEIGHT_MAX.
+ */
+
+ RegRead32 (Private, HTOTAL(PIPE_A), &Val32);
+ Display->HActive = (Val32 & 0xFFF) + 1;
+ RegRead32 (Private, VTOTAL(PIPE_A), &Val32);
+ Display->VActive = (Val32 & 0xFFF) + 1;
+
+ if (Display->HActive != 0 && Display->VActive != 0) {
+ Width = Display->HActive;
+ Height = Display->VActive;
+ if (Display->HActive > DISPLAY_WIDTH_MAX ||
+ Display->VActive > DISPLAY_HEIGHT_MAX) {
+ Width = DISPLAY_WIDTH_MAX;
+ Height = DISPLAY_HEIGHT_MAX;
+ }
+ } else {
+ Width = DISPLAY_WIDTH_DEFAULT;
+ Height = DISPLAY_HEIGHT_DEFAULT;
+ }
+
+ Display->Width = Width;
+ Display->Height = Height;
+ Display->Format = PixelBlueGreenRedReserved8BitPerColor;
+ Display->Bpp = 4;
+ Display->MaxMode = 1;
+
+ // Add default if defined
+ if (PcdGet32 (PcdVideoHorizontalResolution) != 0 &&
+ PcdGet32 (PcdVideoVerticalResolution) != 0 &&
+ PcdGet32 (PcdVideoHorizontalResolution) != Width &&
+ PcdGet32 (PcdVideoVerticalResolution) != Height) {
+ ++Display->MaxMode;
+ }
+
+ Display->CurrentMode = DISPLAY_MODE_INVALID;
+ Display->FrameBufferBltConfigure = NULL;
+ Display->FrameBufferBltConfigureSize = 0;
+
+ // Linear must start at 256K, stride align at 64
+ Display->WidthBytes = Display->Width * Display->Bpp;
+ Display->StrideBytes = ALIGN_VALUE (Display->WidthBytes, 64);
+ Display->FbSize = Display->StrideBytes * Display->Height;
+ Display->Pages = EFI_SIZE_TO_PAGES (Display->FbSize);
+
+ Display->FbGMAddr = VirtualGpu->GpuMemAddr + VirtualGpu->VisibleOffset;
+ Display->FbGMAddr = ALIGN_VALUE (Display->FbGMAddr, SIZE_256KB);
+
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiReservedMemoryType,
+ Display->Pages,
+ &Display->FbPhysicalAddr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePages failed for display FB, pages %d, size %lx, status %d\n",
+ Display->Pages, Display->FbSize, Status
+ );
+ return Status;
+ }
+
+ Status = UpdateGGTT (Private,
+ Display->FbGMAddr,
+ Display->FbPhysicalAddr,
+ Display->Pages
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to Update GGTT for display, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+ Status = IntelVirtualGpuBltVideoFill (
+ Display,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}},
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height});
+ gBS->RestoreTPL (OriginalTPL);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to clear rectangle at [%d, %d] size %dx%d with color 0x%08x, status %d\n",
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.X,
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.Y,
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.Width,
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.Height,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}}.Raw,
+ Status
+ );
+ goto Done;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode,
+ (VOID **)&Display->ModeList
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for display mode list, size %d, status %d\n",
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode,
+ Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ for (ModeNumber = 0; ModeNumber < Display->MaxMode; ModeNumber++) {
+ Display->ModeList[ModeNumber].Version = 0;
+ Display->ModeList[ModeNumber].HorizontalResolution = Display->Width;
+ Display->ModeList[ModeNumber].VerticalResolution = Display->Height;
+ Display->ModeList[ModeNumber].PixelFormat = Display->Format;
+ Display->ModeList[ModeNumber].PixelsPerScanLine = Display->Width;
+ }
+ if (Display->MaxMode > 1) {
+ Display->ModeList[1].HorizontalResolution = PcdGet32 (PcdVideoHorizontalResolution);
+ Display->ModeList[1].VerticalResolution = PcdGet32 (PcdVideoVerticalResolution);
+ Display->ModeList[1].PixelsPerScanLine = PcdGet32 (PcdVideoHorizontalResolution);
+ }
+
+ Private->GraphicsOutputProtocol.QueryMode = IntelVirtualGpuQueryMode;
+ Private->GraphicsOutputProtocol.SetMode = IntelVirtualGpuSetMode;
+ Private->GraphicsOutputProtocol.Blt = IntelVirtualGpuBlt;
+ Private->GraphicsOutputProtocol.Mode->MaxMode = Display->MaxMode;
+ Private->GraphicsOutputProtocol.Mode->Mode = Display->CurrentMode;
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo =
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode;
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo,
+ (VOID **)&Private->GraphicsOutputProtocol.Mode->Info
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for display mode info, size %d, status %d\n",
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo, Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ CopyMem (
+ Private->GraphicsOutputProtocol.Mode->Info,
+ Display->ModeList,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode
+ );
+
+ Private->GraphicsOutputProtocol.Mode->FrameBufferBase = Display->FbGMAddr;
+ Private->GraphicsOutputProtocol.Mode->FrameBufferSize = Display->FbSize;
+
+ InstallVbeShim (L"GVT-g VBIOS", Display->FbGMAddr);
+
+ GVT_DEBUG (EFI_D_INFO,
+ "modes %d, max %dx%d, OVMF default %dx%d\n",
+ Display->MaxMode,
+ Display->Width, Display->Height,
+ PcdGet32 (PcdVideoHorizontalResolution),
+ PcdGet32 (PcdVideoVerticalResolution)
+ );
+ for (ModeNumber = 0; ModeNumber < Display->MaxMode; ModeNumber++) {
+ GVT_DEBUG (EFI_D_INFO,
+ " mode %d: %dx%d BGRX, stride %d\n",
+ ModeNumber,
+ Display->ModeList[ModeNumber].HorizontalResolution,
+ Display->ModeList[ModeNumber].VerticalResolution,
+ ALIGN_VALUE (Display->ModeList[ModeNumber].HorizontalResolution * Display->Bpp, 64)
+ );
+ }
+ GVT_DEBUG (EFI_D_INFO,
+ "FrameBuffer: GMADR %lx, PADDR %lx, size %lx, pages %d, INTERNAL_BLT %d\n",
+ Display->FbGMAddr, Display->FbPhysicalAddr, Display->FbSize, Display->Pages,
+ DISPLAY_USE_INTERNAL_BLT
+ );
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+
+}
+
+EFI_STATUS
+IntelVirtualGpuDisplayClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (Private->GraphicsOutputProtocol.Mode->Info) {
+ Status = gBS->FreePool (Private->GraphicsOutputProtocol.Mode->Info);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePool failed for display mode info, size %d, status %d\n",
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo, Status
+ );
+ goto Done;
+ }
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo = 0;
+ Private->GraphicsOutputProtocol.Mode->Info = NULL;
+ }
+ Private->GraphicsOutputProtocol.Mode->MaxMode = 0;
+ Private->GraphicsOutputProtocol.Mode->Mode = DISPLAY_MODE_INVALID;
+
+ if (Display->FbPhysicalAddr) {
+ Status = gBS->FreePages (Display->FbPhysicalAddr, Display->Pages);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePages failed for display FB, pages %d, size %lx, status %d\n",
+ Display->Pages, Display->FbSize, Status
+ );
+ goto Done;
+ }
+ Display->FbPhysicalAddr = 0;
+ Display->Pages = 0;
+ Display->FbSize = 0;
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (This);
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)GvtGopPrivate->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (ModeNumber >= Display->MaxMode) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Invalid ModeNumber, request %d, max %d, status %d\n",
+ ModeNumber, Display->MaxMode, Status
+ );
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ (VOID **)Info
+ );
+ if (EFI_ERROR (Status) || *Info == NULL) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for queried mode info, size %d, status %d\n",
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+ CopyMem (
+ *Info,
+ &Display->ModeList[ModeNumber],
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
+ );
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (This);
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)GvtGopPrivate->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (ModeNumber >= Display->MaxMode) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Invalid ModeNumber, request %d, max %d, status %d\n",
+ ModeNumber, Display->MaxMode, Status
+ );
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+#if (DISPLAY_USE_INTERNAL_BLT == 1)
+ Status = IntelVirtualGpuBltVideoFill (
+ Display,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}},
+ (BLT_RECTANGLE){0, 0, This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution});
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "IntelVirtualGpuBltVideoFill failed for mode %d, status %d\n",
+ ModeNumber,
+ Status
+ );
+ }
+#else
+ Status = FrameBufferBltConfigure (
+ (VOID*) (UINTN) This->Mode->FrameBufferBase,
+ This->Mode->Info,
+ Display->FrameBufferBltConfigure,
+ &Display->FrameBufferBltConfigureSize
+ );
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ if (Display->FrameBufferBltConfigure != NULL) {
+ Status = gBS->FreePool (Display->FrameBufferBltConfigure);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePool failed for FrameBufferBltConfigure, status %d\n",
+ Status
+ );
+ goto Done;
+ }
+ }
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ Display->FrameBufferBltConfigureSize,
+ (VOID **)&Display->FrameBufferBltConfigure
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for FrameBufferBltConfigure, size %d, status %d\n",
+ Display->FrameBufferBltConfigureSize,
+ Status
+ );
+ goto Done;
+ }
+
+ Status = FrameBufferBltConfigure (
+ (VOID*) (UINTN) This->Mode->FrameBufferBase,
+ This->Mode->Info,
+ Display->FrameBufferBltConfigure,
+ &Display->FrameBufferBltConfigureSize
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FrameBufferBltConfigure failed for mode %d, status %d\n",
+ ModeNumber,
+ Status
+ );
+ goto Done;
+ }
+ }
+
+ Status = FrameBufferBlt (
+ Display->FrameBufferBltConfigure,
+ &(EFI_GRAPHICS_OUTPUT_BLT_PIXEL){0, 0, 0, 0},
+ EfiBltVideoFill,
+ 0, 0,
+ 0, 0,
+ This->Mode->Info->HorizontalResolution,
+ This->Mode->Info->VerticalResolution,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FrameBufferBlt BltOperation %d failed for mode %d, color 0x%08x, status %d\n",
+ EfiBltVideoFill,
+ ModeNumber,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}}.Raw,
+ Status
+ );
+ }
+#endif
+
+ Status = IntelVirtualGpuEnableDisplay (
+ GvtGopPrivate,
+ ModeNumber,
+ FALSE
+ );
+
+ Status = IntelVirtualGpuEnableDisplay (
+ GvtGopPrivate,
+ ModeNumber,
+ TRUE
+ );
+
+ // Set current mode info in GOP
+ This->Mode->Mode = ModeNumber;
+ CopyMem (
+ This->Mode->Info,
+ &Display->ModeList[ModeNumber],
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
+ );
+
+ GVT_DEBUG (EFI_D_INFO, "Set mode %d, %dx%d, status %d\n",
+ ModeNumber,
+ Display->ModeList[ModeNumber].HorizontalResolution,
+ Display->ModeList[ModeNumber].VerticalResolution,
+ Status
+ );
+
+Done:
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+ EFI_TPL OriginalTPL;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (This);
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)GvtGopPrivate->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+#if (DISPLAY_USE_INTERNAL_BLT == 1)
+ switch (BltOperation) {
+ case EfiBltVideoFill:
+ Status = IntelVirtualGpuBltVideoFill (
+ Display,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION)(*BltBuffer),
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height});
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ break;
+ case EfiBltVideoToBltBuffer:
+ Status = IntelVirtualGpuBltVideoToBuffer (
+ Display,
+ BltBuffer,
+ (BLT_RECTANGLE){SourceX, SourceY, Width, Height},
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height},
+ Delta
+ );
+ break;
+ case EfiBltBufferToVideo:
+ Status = IntelVirtualGpuBltVideoFromBuffer (
+ Display,
+ BltBuffer,
+ (BLT_RECTANGLE){SourceX, SourceY, Width, Height},
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height},
+ Delta
+ );
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ break;
+ case EfiBltVideoToVideo:
+ Status = IntelVirtualGpuBltVideoToVideo (
+ Display,
+ (BLT_RECTANGLE){SourceX, SourceY, Width, Height},
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height}
+ );
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ break;
+ default:
+ GVT_DEBUG (EFI_D_INFO, "Unsupported EFI_GRAPHICS_OUTPUT_BLT_OPERATION %d\n", BltOperation);
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+#else
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+ case EfiBltVideoFill:
+ case EfiBltBufferToVideo:
+ case EfiBltVideoToVideo:
+ Status = FrameBufferBlt (
+ Display->FrameBufferBltConfigure,
+ BltBuffer,
+ BltOperation,
+ SourceX,
+ SourceY,
+ DestinationX,
+ DestinationY,
+ Width,
+ Height,
+ Delta
+ );
+ if (BltOperation != EfiBltVideoToBltBuffer) {
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ }
+ break;
+ default:
+ GVT_DEBUG (EFI_D_INFO, "Unsupported EFI_GRAPHICS_OUTPUT_BLT_OPERATION %d\n", BltOperation);
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+#endif
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuEnableDisplay (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 ModeNumber,
+ IN BOOLEAN Enable
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+ UINT32 Width, Height, Val32;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (ModeNumber >= Display->MaxMode) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Invalid ModeNumber, request %d, max %d, status %d\n",
+ ModeNumber, Display->MaxMode, Status
+ );
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Width = Display->ModeList[ModeNumber].HorizontalResolution;
+ Height = Display->ModeList[ModeNumber].VerticalResolution;
+
+ if (Enable) {
+ Display->CurrentMode = ModeNumber;
+
+ Val32 = (Display->HActive - 1) << 16;
+ Val32 |= Display->VActive;
+ RegWrite32 (Private, PIPESRC(PIPE_A), Val32);
+
+ RegRead32 (Private, PIPE_CONF(PIPE_A), &Val32);
+ Val32 |= PIPE_CONF_ENABLE;
+ RegWrite32 (Private, PIPE_CONF(PIPE_A), Val32);
+
+ Val32 = (Width - 1) & 0xFFF;
+ Val32 |= ((Height - 1) & 0xFFF) << 16;
+ RegWrite32 (Private, PLANE_SIZE(PIPE_A, PLANE_PRIMARY), Val32);
+ RegWrite32 (Private, PLANE_POS(PIPE_A, PLANE_PRIMARY), 0);
+
+ // Convert mode with to stride in chunks of 64 bytes as required by PLANE_STRIDE
+ Val32 = Display->ModeList[ModeNumber].HorizontalResolution * Display->Bpp;
+ Val32 = ALIGN_VALUE (Val32, 64);
+ Val32 = (Val32 / 64) & PLANE_STRIDE_MASK;
+ RegWrite32 (Private, PLANE_STRIDE(PIPE_A, PLANE_PRIMARY), Val32);
+
+ RegWrite32 (Private, PLANE_SURF(PIPE_A, PLANE_PRIMARY), Display->FbGMAddr);
+
+ // Stretch to fullscreen if current mode is smaller than H/V active.
+ if (Display->HActive != Width ||
+ Display->VActive != Height) {
+ RegWrite32 (Private, PS_WIN_POS(PIPE_A, 0), 0);
+ RegWrite32 (Private,
+ PS_WIN_SZ(PIPE_A, 0),
+ Display->HActive << 16 | Display->VActive
+ );
+ RegRead32 (Private, PS_CTRL(PIPE_A, 0), &Val32);
+ Val32 |= PS_CTRL_SCALER_EN;
+ Val32 &= ~PS_CTRL_SCALER_MODE_MASK;
+ Val32 |= PS_CTRL_SCALER_MODE_DYN;
+ Val32 &= ~PS_CTRL_SCALER_BINDING_MASK;
+ Val32 |= PS_CTRL_PLANE_SEL(PLANE_PRIMARY);
+ Val32 &= ~PS_CTRL_SCALER_FILTER_MASK;
+ Val32 |= PS_CTRL_SCALER_FILTER_MEDIUM;
+ RegWrite32 (Private, PS_CTRL(PIPE_A, 0), Val32);
+ }
+
+ RegRead32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), &Val32);
+ Val32 |= PLANE_CTL_ENABLE;
+ Val32 &= ~PLANE_CTL_PIPE_GAMMA_ENABLE;
+ Val32 &= ~PLANE_CTL_FORMAT_MASK;
+ Val32 |= PLANE_CTL_FORMAT_XRGB_8888;
+ Val32 &= ~PLANE_CTL_PIPE_CSC_ENABLE;
+ Val32 &= ~PLANE_CTL_KEY_ENABLE_MASK;
+ Val32 &= ~PLANE_CTL_ORDER_RGBX;
+ if (Display->ModeList[ModeNumber].PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
+ Val32 |= PLANE_CTL_ORDER_RGBX;
+ }
+ Val32 &= ~PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
+ Val32 |= PLANE_CTL_PLANE_GAMMA_DISABLE;
+ Val32 &= ~PLANE_CTL_TILED_MASK;
+ Val32 |= PLANE_CTL_TILED_LINEAR;
+ Val32 &= ~PLANE_CTL_ASYNC_FLIP;
+ Val32 &= ~PLANE_CTL_ALPHA_MASK;
+ Val32 |= PLANE_CTL_ALPHA_DISABLE;
+ Val32 &= ~PLANE_CTL_ROTATE_MASK;
+ Val32 |= PLANE_CTL_ROTATE_0;
+ RegWrite32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), Val32);
+ } else {
+ Display->CurrentMode = DISPLAY_MODE_INVALID;
+
+ RegRead32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), &Val32);
+ Val32 &= ~PLANE_CTL_ENABLE;
+ RegWrite32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), Val32);
+ RegWrite32 (Private, PLANE_SURF(PIPE_A, PLANE_PRIMARY), 0);
+
+ RegRead32 (Private, PS_CTRL(PIPE_A, 0), &Val32);
+ Val32 &= ~PS_CTRL_SCALER_EN;
+ RegWrite32 (Private, PS_CTRL(PIPE_A, 0), Val32);
+ RegWrite32 (Private, PS_WIN_POS(PIPE_A, 0), 0);
+ RegWrite32 (Private, PS_WIN_SZ(PIPE_A, 0), 0);
+
+ RegRead32 (Private, PIPE_CONF(PIPE_A), &Val32);
+ Val32 &= ~PIPE_CONF_ENABLE;
+ RegWrite32 (Private, PIPE_CONF(PIPE_A), Val32);
+ }
+
+ Status = EFI_SUCCESS;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: %a mode %dx%d 0x%x, scaling %a\n",
+ __FUNCTION__,
+ Enable ? "Enable" : "Disable",
+ Width,
+ Height,
+ Display->FbGMAddr,
+ (Display->HActive != Width ||
+ Display->VActive != Height) ? "On" : "Off");
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuNotifyDisplayReady (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN BOOLEAN Ready
+ )
+{
+ return RegWrite32 (
+ Private,
+ vgtif_reg(display_ready),
+ Ready ? VGT_DRV_DISPLAY_READY : VGT_DRV_DISPLAY_NOT_READY
+ );
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFill (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltPixel,
+ IN BLT_RECTANGLE Destination
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *DestAddr;
+ UINTN DestBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Destination.Width == 0 || Destination.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoFill invalid destination rectangle [%d, %d] \n",
+ Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Destination.X + Destination.Width > Display->Width) ||
+ (Destination.Y + Destination.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoFill destination [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Destination.X, Destination.Y,
+ Destination.X + Destination.Width, Destination.Y + Destination.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ if (Destination.Width * Display->Bpp == ModeStrideBytes) {
+ DestAddr = (UINT8*)Display->FbGMAddr + Destination.Y * ModeStrideBytes;
+ DestBytes = Destination.Width * Display->Bpp * Destination.Height;
+ SetMem32 ((VOID*)DestAddr, DestBytes, BltPixel.Raw);
+ } else {
+
+ for (Line = 0; Line < Destination.Height; Line++) {
+ DestAddr = (UINT8*)Display->FbGMAddr +
+ (Line + Destination.Y) * ModeStrideBytes +
+ Destination.X * Display->Bpp;
+ DestBytes = Destination.Width * Display->Bpp;
+
+ SetMem32 (DestAddr, DestBytes, BltPixel.Raw);
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *SourceAddr, *DestAddr;
+ UINTN DestStride, CopyBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Source.Width == 0 || Source.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToBltBuffer invalid source rectangle [%d, %d] \n",
+ Source.Width, Source.Height
+ );
+ goto Done;
+ }
+
+ if (Source.Width != Destination.Width ||
+ Source.Height != Destination.Height) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToBltBuffer size mismatch: source %dx%d, destination %dx%d\n",
+ Source.Width, Source.Height, Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Source.X + Source.Width > Display->Width) ||
+ (Source.Y + Source.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToBltBuffer source [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Source.X, Source.Y,
+ Source.X + Source.Width, Source.Y + Source.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Destination.X != 0 || Destination.Y != 0) {
+ DestStride = Delta;
+ } else {
+ DestStride = Destination.Width * Display->Bpp;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ for (Line = 0; Line < Source.Height; Line++) {
+ SourceAddr = (UINT8*)Display->FbGMAddr +
+ (Source.Y + Line) * ModeStrideBytes +
+ Source.X * Display->Bpp;
+ DestAddr = (UINT8*)BltBuffer + (Destination.Y + Line) * DestStride;
+ DestAddr = (UINT8*)DestAddr + Destination.X * Display->Bpp;
+ CopyBytes = Source.Width * Display->Bpp;
+ CopyMem (DestAddr, SourceAddr, CopyBytes);
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "EfiBltVideoToBltBuffer [%d, %d] >> [%d, %d] size [%d, %d] Delta %d\n",
+ Source.X, Source.Y,
+ Destination.X, Destination.Y,
+ Source.Width, Source.Height,
+ Delta
+ );
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFromBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *SourceAddr, *DestAddr;
+ UINTN SourceStride, CopyBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Source.Width == 0 || Source.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltBufferToVideo invalid source rectangle [%d, %d] \n",
+ Source.Width, Source.Height
+ );
+ goto Done;
+ }
+
+ if (Source.Width != Destination.Width || Source.Height != Destination.Height) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltBufferToVideo size mismatch: source %dx%d, destination %dx%d\n",
+ Source.Width, Source.Height, Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Destination.X + Destination.Width > Display->Width) ||
+ (Destination.Y + Destination.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltBufferToVideo destination [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Destination.X, Destination.Y,
+ Destination.X + Destination.Width, Destination.Y + Destination.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Source.X != 0 || Source.Y != 0) {
+ SourceStride = Delta;
+ } else {
+ SourceStride = Source.Width * Display->Bpp;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ for (Line = 0; Line < Source.Height; Line++) {
+ SourceAddr = (UINT8*)BltBuffer +
+ (Source.Y + Line) * SourceStride +
+ Source.X * Display->Bpp;
+ DestAddr = (UINT8*)Display->FbGMAddr +
+ (Destination.Y + Line) * ModeStrideBytes +
+ Destination.X * Display->Bpp;
+ CopyBytes = Source.Width * Display->Bpp;
+ CopyMem (DestAddr, SourceAddr, CopyBytes);
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "EfiBltBufferToVideo [%d, %d] >> [%d, %d] size [%d, %d] Delta %d\n",
+ Source.X, Source.Y,
+ Destination.X, Destination.Y,
+ Source.Width, Source.Height,
+ Delta
+ );
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToVideo (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *SourceAddr, *DestAddr;
+ UINTN CopyBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Source.Width == 0 || Source.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo invalid source rectangle [%d, %d] \n",
+ Source.Width, Source.Height
+ );
+ goto Done;
+ }
+
+ if (Source.Width != Destination.Width || Source.Height != Destination.Height) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo size mismatch: source %dx%d, destination %dx%d\n",
+ Source.Width, Source.Height, Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Source.X + Source.Width > Display->Width) ||
+ (Source.Y + Source.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo source [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Source.X, Source.Y,
+ Source.X + Source.Width, Source.Y + Source.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if ((Destination.X + Destination.Width > Display->Width) ||
+ (Destination.Y + Destination.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo destination [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Destination.X, Destination.Y,
+ Destination.X + Destination.Width, Destination.Y + Destination.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ for (Line = 0; Line < Source.Height; Line++) {
+ SourceAddr = (UINT8*)Display->FbGMAddr +
+ (Source.Y + Line) * ModeStrideBytes +
+ Source.X * Display->Bpp;
+ DestAddr = (UINT8*)Display->FbGMAddr +
+ (Destination.Y + Line)* ModeStrideBytes +
+ Destination.X * Display->Bpp;
+ CopyBytes = Source.Width * Display->Bpp;
+ //
+ // Overlap could corrupt source content:
+ // src <----|---->
+ // dst <----|---->
+ //
+ if (DestAddr > SourceAddr && DestAddr < (SourceAddr + CopyBytes)) {
+ CopyMem (
+ SourceAddr + CopyBytes,
+ DestAddr,
+ SourceAddr + CopyBytes - DestAddr
+ );
+ CopyMem (DestAddr, SourceAddr, DestAddr - SourceAddr);
+ //
+ // Overlap won't corrupt source content:
+ // src <----|---->
+ // dst <----|---->
+ //
+ // No overlap
+ // src <--------->
+ // dst <--------->
+ //
+ } else {
+ CopyMem (DestAddr, SourceAddr, CopyBytes);
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/Display.h b/OvmfPkg/IntelGvtGopDxe/Display.h
new file mode 100644
index 000000000000..19e4d64f3b12
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Display.h
@@ -0,0 +1,141 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __DISPLAY_H_
+#define __DISPLAY_H_
+
+#include <Library/FrameBufferBltLib.h>
+
+typedef struct _BLT_RECTANGLE {
+ UINTN X;
+ UINTN Y;
+ UINTN Width;
+ UINTN Height;
+} BLT_RECTANGLE, *PBLT_RECTANGLE;
+
+#define DISPLAY_WIDTH_MAX 1920
+#define DISPLAY_HEIGHT_MAX 1080
+#define DISPLAY_WIDTH_DEFAULT 1024
+#define DISPLAY_HEIGHT_DEFAULT 768
+#define DISPLAY_MODE_INVALID 0xFFFF
+
+#define DISPLAY_USE_INTERNAL_BLT 1
+
+typedef struct _INTEL_VIRTUAL_GPU_DISPLAY {
+ UINTN HActive;
+ UINTN VActive;
+ UINTN Width;
+ UINTN Height;
+ UINTN WidthBytes;
+ UINTN StrideBytes;
+ EFI_GRAPHICS_PIXEL_FORMAT Format;
+ UINTN Bpp;
+ UINTN MaxMode;
+ UINTN CurrentMode;
+ UINTN FbSize;
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS FbGMAddr;
+ EFI_PHYSICAL_ADDRESS FbPhysicalAddr;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeList;
+ FRAME_BUFFER_CONFIGURE *FrameBufferBltConfigure;
+ UINTN FrameBufferBltConfigureSize;
+} INTEL_VIRTUAL_GPU_DISPLAY, *PINTEL_VIRTUAL_GPU_DISPLAY;
+
+EFI_STATUS
+IntelVirtualGpuDisplayInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+IntelVirtualGpuDisplayClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ );
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ );
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ );
+
+EFI_STATUS
+IntelVirtualGpuEnableDisplay (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 ModeNumber,
+ IN BOOLEAN Enable
+ );
+
+EFI_STATUS
+IntelVirtualGpuNotifyDisplayReady (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN BOOLEAN Ready
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFill (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltPixel,
+ IN BLT_RECTANGLE Destination
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFromBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToVideo (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination
+ );
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ );
+
+#endif //__DISPLAY_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/GopDriver.c b/OvmfPkg/IntelGvtGopDxe/GopDriver.c
new file mode 100644
index 000000000000..396e5cf4447c
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/GopDriver.c
@@ -0,0 +1,478 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "VirtualGpu.h"
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gGvtGopDriverComponentName = {
+ GvtGopComponentNameGetDriverName,
+ GvtGopComponentNameGetControllerName,
+ "eng"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gGvtGopDriverComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GvtGopComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GvtGopComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE gGvtGopDriverNameTable[] = {
+ { "eng;en", L"Intel GVT-g GOP Driver" },
+ { NULL , NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE gGvtGopControllerNameTable[] = {
+ { "eng;en", L"Intel GVT-g Virtual GPU PCI Adapter" },
+ { NULL , NULL }
+};
+
+STATIC
+EFI_STATUS
+EFIAPI
+GvtGopBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "OpenProtocol gEfiPciIoProtocolGuid failed with %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = IntelVirtualGpuActive (PciIo);
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+Done:
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+GvtGopBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OriginalTPL;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ UINT64 PciAttr;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
+ EFI_PCI_IO_PROTOCOL *ChildPciIo;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ OriginalTPL = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(GVT_GOP_PRIVATE_DATA),
+ (VOID **)&GvtGopPrivate
+ );
+ if (EFI_ERROR (Status) || GvtGopPrivate == NULL) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for GVT_GOP_PRIVATE_DATA, size %d, status %d\n",
+ sizeof(GVT_GOP_PRIVATE_DATA), Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ZeroMem (GvtGopPrivate, sizeof(GVT_GOP_PRIVATE_DATA));
+ GvtGopPrivate->Signature = GVT_GOP_MAGIC;
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(INTEL_VIRTUAL_GPU),
+ &GvtGopPrivate->VirtualGpu
+ );
+ if (EFI_ERROR (Status) || GvtGopPrivate->VirtualGpu == NULL) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for INTEL_VIRTUAL_GPU, size %d, status %d\n",
+ sizeof(INTEL_VIRTUAL_GPU), Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Free;
+ }
+ ZeroMem (GvtGopPrivate->VirtualGpu, sizeof(INTEL_VIRTUAL_GPU));
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &GvtGopPrivate->PciIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't open protocol gEfiPciIoProtocolGuid, status %d\n", Status
+ );
+ goto Free;
+ }
+
+ Status = GvtGopPrivate->PciIo->Attributes (
+ GvtGopPrivate->PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &GvtGopPrivate->OriginalPciAttr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed EfiPciIoAttributeOperationGet, status %d\n", Status
+ );
+ goto Free;
+ }
+
+ PciAttr = EFI_PCI_DEVICE_ENABLE;
+ Status = GvtGopPrivate->PciIo->Attributes (
+ GvtGopPrivate->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ PciAttr,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed EfiPciIoAttributeOperationEnable %llx, status %d\n", PciAttr,
+ Status
+ );
+ goto Free;
+ }
+
+ Status = IntelVirtualGpuInit (GvtGopPrivate);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Failed IntelVirtualGpuInit, status %d\n", Status);
+ goto Free;
+ }
+
+ Status = gBS->HandleProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Fail gEfiDevicePathProtocolGuid, status %d\n",
+ Status
+ );
+ goto Free;
+ }
+
+ ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
+ AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
+ AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
+ AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, 0, 0);
+ SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+ GvtGopPrivate->GopDevPath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
+ );
+ if (GvtGopPrivate->GopDevPath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR, "Fail AppendDevicePathNode, status %d\n", Status);
+ goto Free;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &GvtGopPrivate->Handle,
+ &gEfiDevicePathProtocolGuid,
+ GvtGopPrivate->GopDevPath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't install protocol gEfiDevicePathProtocolGuid, status %d\n",
+ Status
+ );
+ goto Free;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &GvtGopPrivate->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &GvtGopPrivate->GraphicsOutputProtocol,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't install protocol gEfiGraphicsOutputProtocolGuid, status %d\n",
+ Status
+ );
+ goto Free;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &ChildPciIo,
+ This->DriverBindingHandle,
+ GvtGopPrivate->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Free;
+ }
+
+ goto Done;
+
+Free:
+ if (GvtGopPrivate->PciIo) {
+ if (GvtGopPrivate->OriginalPciAttr) {
+ GvtGopPrivate->PciIo->Attributes (
+ GvtGopPrivate->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ GvtGopPrivate->OriginalPciAttr,
+ NULL
+ );
+ }
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ GvtGopPrivate->PciIo = NULL;
+ }
+
+ if (GvtGopPrivate->VirtualGpu) {
+ gBS->FreePool (GvtGopPrivate->VirtualGpu);
+ GvtGopPrivate->VirtualGpu = NULL;
+ }
+
+ if (GvtGopPrivate) {
+ gBS->FreePool (GvtGopPrivate);
+ }
+
+ if (GvtGopPrivate->GopDevPath) {
+ FreePool (GvtGopPrivate->GopDevPath);
+ GvtGopPrivate->GopDevPath = NULL;
+ }
+
+Done:
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+GvtGopBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutputProtocol;
+ EFI_STATUS Status;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+
+ GVT_DEBUG (EFI_D_INFO, "%a: >>>\n", __FUNCTION__);
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **)&GraphicsOutputProtocol,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_STARTED;
+ goto Done;
+ }
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutputProtocol);
+ if (!GvtGopPrivate) {
+ Status = EFI_NOT_STARTED;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Intel GVT-g GOP isn't started, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ GvtGopPrivate->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &GvtGopPrivate->GraphicsOutputProtocol,
+ NULL
+ );
+
+ if (GvtGopPrivate->PciIo) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ GvtGopPrivate->PciIo = NULL;
+ }
+
+ Status = IntelVirtualGpuClean (GvtGopPrivate);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Fail to clean virtual GPU, status %d\n", Status);
+ goto Done;
+ }
+
+ if (GvtGopPrivate->VirtualGpu) {
+ gBS->FreePool (GvtGopPrivate->VirtualGpu);
+ GvtGopPrivate->VirtualGpu = NULL;
+ }
+
+ if (GvtGopPrivate) {
+ gBS->FreePool (GvtGopPrivate);
+ }
+
+Done:
+
+ GVT_DEBUG (EFI_D_INFO, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+STATIC EFI_DRIVER_BINDING_PROTOCOL gGvtGopDriverBinding = {
+ GvtGopBindingSupported,
+ GvtGopBindingStart,
+ GvtGopBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ gGvtGopDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gGvtGopDriverComponentName)
+ );
+}
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gGvtGopDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ gGvtGopControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gGvtGopDriverComponentName)
+ );
+}
+
+EFI_STATUS
+EFIAPI
+GvtGopEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gGvtGopDriverBinding,
+ ImageHandle,
+ &gGvtGopDriverComponentName,
+ &gGvtGopDriverComponentName2);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Failed to install driver %d : %d\n", Status);
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/GpuReg.c b/OvmfPkg/IntelGvtGopDxe/GpuReg.c
new file mode 100644
index 000000000000..778c09d5198c
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/GpuReg.c
@@ -0,0 +1,91 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GpuReg.h"
+
+EFI_STATUS
+RegRead32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ OUT UINT32 *ValuePtr
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+
+ if (Offset < MMIO_SIZE && ValuePtr != NULL) {
+ Status = Private->PciIo->Mem.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ Offset,
+ 1,
+ ValuePtr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, *ValuePtr, Status
+ );
+ } else {
+ Status = EFI_SUCCESS;
+ GVT_DEBUG (EFI_D_VERBOSE, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, *ValuePtr, Status
+ );
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR,
+ "%a invalid reg %x or ValuePtr %p, status %d\n",
+ __FUNCTION__, Offset, ValuePtr, Status
+ );
+ goto Done;
+ }
+
+Done:
+ return Status;
+}
+
+EFI_STATUS
+RegWrite32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+
+ if (Offset < MMIO_SIZE) {
+ Status = Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ Offset,
+ 1,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, Value, Status
+ );
+ } else {
+ Status = EFI_SUCCESS;
+ GVT_DEBUG (EFI_D_VERBOSE, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, Value, Status
+ );
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR, "%a invalid reg %x, status %d\n",
+ __FUNCTION__, Offset, Status
+ );
+ goto Done;
+ }
+
+Done:
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/GpuReg.h b/OvmfPkg/IntelGvtGopDxe/GpuReg.h
new file mode 100644
index 000000000000..f46f4cef9cd4
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/GpuReg.h
@@ -0,0 +1,175 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __GPUREG_H_
+#define __GPUREG_H_
+
+#include "Common.h"
+
+#define MMIO_SIZE 0x200000
+
+#define VGT_PVINFO_PAGE 0x78000
+#define VGT_PVINFO_SIZE 0x1000
+
+#define VGT_MAGIC 0x4776544776544776ULL /* 'vGTvGTvG' */
+#define VGT_VERSION_MAJOR 1
+#define VGT_VERSION_MINOR 0
+
+#define VGT_DRV_DISPLAY_NOT_READY 0
+#define VGT_DRV_DISPLAY_READY 1
+
+struct vgt_if {
+ UINT64 magic; /* VGT_MAGIC */
+ UINT16 version_major;
+ UINT16 version_minor;
+ UINT32 vgt_id; /* ID of vGT instance */
+ UINT32 vgt_caps; /* VGT capabilities */
+ UINT32 rsv1[11]; /* pad to offset 0x40 */
+ /*
+ * Data structure to describe the balooning info of resources.
+ * Each VM can only have one portion of continuous area for now.
+ * (May support scattered resource in future)
+ * (starting from offset 0x40)
+ */
+ struct {
+ /* Aperture register balooning */
+ struct {
+ UINT32 base;
+ UINT32 size;
+ } mappable_gmadr; /* aperture */
+ /* GMADR register balooning */
+ struct {
+ UINT32 base;
+ UINT32 size;
+ } nonmappable_gmadr; /* non aperture */
+ /* allowed fence registers */
+ UINT32 fence_num;
+ UINT32 rsv2[3];
+ } avail_rs; /* available/assigned resource */
+ UINT32 rsv3[0x200 - 24]; /* pad to half page */
+ /*
+ * The bottom half page is for response from Gfx driver to hypervisor.
+ */
+ UINT32 rsv4;
+ UINT32 display_ready; /* ready for display owner switch */
+
+ UINT32 rsv5[4];
+
+ UINT32 g2v_notify;
+ UINT32 rsv6[5];
+
+ UINT32 cursor_x_hot;
+ UINT32 cursor_y_hot;
+
+ struct {
+ UINT32 lo;
+ UINT32 hi;
+ } pdp[4];
+
+ UINT32 execlist_context_descriptor_lo;
+ UINT32 execlist_context_descriptor_hi;
+
+ UINT32 rsv7[0x200 - 24]; /* pad to one page */
+} PACKED;
+
+#define vgtif_offset(x) (OFFSET_OF(struct vgt_if, x))
+#define vgtif_reg(x) (VGT_PVINFO_PAGE + vgtif_offset(x))
+
+typedef enum _GPU_DISPLAY_PIPE {
+ PIPE_INVALID = -1,
+ PIPE_A = 0,
+ PIPE_B,
+ PIPE_C,
+ PIPE_MAX = PIPE_C
+} GPU_DISPLAY_PIPE;
+
+typedef enum _GPU_DISPLAY_PLANE {
+ PLANE_PRIMARY = 0,
+ PLANE_SPRITE0,
+ PLANE_SPRITE1,
+ PLANE_MAX,
+} GPU_DISPLAY_PLANE;
+
+#define _TRANS_HTOTAL_A 0x60000
+#define _TRANS_VTOTAL_A 0x6000C
+#define _TRANS_REG_OFFSET(trans) (trans * 0x1000)
+
+#define _PS_WIN_POS_1_A 0x68170
+#define _PS_WIN_SZ_1_A 0x68174
+#define _PS_CTRL_1_A 0x68180
+#define _PS_REG_OFFSET(pipe, id) (pipe * 0x800 + id * 0x100)
+#define PS_WIN_POS(pipe, id) (_PS_WIN_POS_1_A + _PS_REG_OFFSET(pipe, id))
+#define PS_WIN_SZ(pipe, id) (_PS_WIN_SZ_1_A + _PS_REG_OFFSET(pipe, id))
+#define PS_CTRL(pipe, id) (_PS_CTRL_1_A + _PS_REG_OFFSET(pipe, id))
+#define PS_CTRL_SCALER_EN (1 << 31)
+#define PS_CTRL_SCALER_MODE_MASK (0x3 << 28)
+#define PS_CTRL_SCALER_MODE_DYN (0 << 28)
+#define PS_CTRL_SCALER_MODE_HQ (1 << 28)
+#define PS_CTRL_SCALER_BINDING_MASK (0x7 << 25)
+#define PS_CTRL_SCALER_BINDING_PIPE (0 << 25)
+#define PS_CTRL_PLANE_SEL(plane) (((plane) + 1) << 25)
+#define PS_CTRL_SCALER_FILTER_MASK (3 << 23)
+#define PS_CTRL_SCALER_FILTER_MEDIUM (0 << 23)
+
+#define PIPE_REG_OFFSET(pipe) (pipe * 0x1000)
+#define _PIPE_CONF_A 0x70008
+#define PIPE_CONF_ENABLE (1 << 31)
+#define _PIPE_SRCSZ_A 0x6001C
+#define PIPE_CONF(pipe) (_PIPE_CONF_A + PIPE_REG_OFFSET(pipe))
+#define PIPESRC(pipe) (_PIPE_SRCSZ_A + PIPE_REG_OFFSET(pipe))
+
+#define _PLANE_CTL_1_A 0x70180
+#define PLANE_CTL_ENABLE (1 << 31)
+#define PLANE_CTL_PIPE_GAMMA_ENABLE (1 << 30)
+#define PLANE_CTL_FORMAT_MASK (0xF << 24)
+#define PLANE_CTL_FORMAT_XRGB_8888 (0x4 << 24)
+#define PLANE_CTL_PIPE_CSC_ENABLE (1 << 23)
+#define PLANE_CTL_KEY_ENABLE_MASK (0x3 << 21)
+#define PLANE_CTL_ORDER_RGBX (1 << 20)
+#define PLANE_CTL_RENDER_DECOMPRESSION_ENABLE (1 << 15)
+#define PLANE_CTL_PLANE_GAMMA_DISABLE (1 << 13)
+#define PLANE_CTL_TILED_MASK (0x7 << 10)
+#define PLANE_CTL_TILED_LINEAR (0 << 10)
+#define PLANE_CTL_ASYNC_FLIP (1 << 9)
+#define PLANE_CTL_ALPHA_MASK (0x3 << 4)
+#define PLANE_CTL_ALPHA_DISABLE (0 << 4)
+#define PLANE_CTL_ROTATE_MASK (0x3 << 0)
+#define PLANE_CTL_ROTATE_0 (0x0 << 0)
+
+#define _PLANE_STRIDE_1_A 0x70188
+#define PLANE_STRIDE_MASK 0x1FF
+#define _PLANE_POS_1_A 0x7018C
+#define _PLANE_SIZE_1_A 0x70190
+#define _PLANE_SURF_1_A 0x7019C
+#define _PLANE_REG_OFFSET(pipe, plane) (pipe * 0x1000 + plane * 0x100)
+
+#define HTOTAL(trans) (_TRANS_HTOTAL_A + _TRANS_REG_OFFSET(trans))
+#define VTOTAL(trans) (_TRANS_VTOTAL_A + _TRANS_REG_OFFSET(trans))
+
+#define PLANE_CTL(pipe, plane) (_PLANE_CTL_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_STRIDE(pipe, plane) (_PLANE_STRIDE_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_POS(pipe, plane) (_PLANE_POS_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_SIZE(pipe, plane) (_PLANE_SIZE_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_SURF(pipe, plane) (_PLANE_SURF_1_A + _PLANE_REG_OFFSET(pipe, plane))
+
+EFI_STATUS
+RegRead32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ OUT UINT32 *ValuePtr
+ );
+
+EFI_STATUS
+RegWrite32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ IN UINT32 Value
+ );
+
+#endif //__GPUREG_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/Gtt.c b/OvmfPkg/IntelGvtGopDxe/Gtt.c
new file mode 100644
index 000000000000..12782eb5afaa
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Gtt.c
@@ -0,0 +1,162 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "Gtt.h"
+#include "VirtualGpu.h"
+
+EFI_STATUS
+GGTTGetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ OUT GTT_PTE_ENTRY *Entry
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+
+ if (Entry == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR,
+ "%a invalid GGTT entry ptr %p at Index %x, status %d\n",
+ __FUNCTION__, Entry, Index, Status
+ );
+ goto Done;
+ }
+
+ PciIo = Private->PciIo;
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+
+ if (Index >= VirtualGpu->VisibleGGTTOffset &&
+ Index < VirtualGpu->VisibleGGTTOffset + VirtualGpu->VisibleGGTTSize) {
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BAR_IDX0,
+ GTT_OFFSET + Index * GTT_ENTRY_SIZE,
+ 1,
+ Entry
+ );
+ if (EFI_ERROR (Status)) {
+ Entry = 0;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed to Get GGTT Entry index %lx, status %d\n", Index, Status
+ );
+ }
+ } else if (Index >= VirtualGpu->InvisibleGGTTOffset &&
+ Index < VirtualGpu->InvisibleGGTTOffset + VirtualGpu->InvisibleGGTTSize) {
+ Status = EFI_UNSUPPORTED;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip get GGTT index %lx for invisible GMADR\n", Index
+ );
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip get GGTT index %lx out-of-range, balloon unsupported\n",
+ Index
+ );
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "Get GGTT Entry %lx at index %lx\n", *Entry, Index);
+
+Done:
+
+ return Status;
+}
+
+EFI_STATUS
+GGTTSetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ IN GTT_PTE_ENTRY Entry
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+
+ PciIo = Private->PciIo;
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+
+ if (Index >= VirtualGpu->VisibleGGTTOffset &&
+ Index < VirtualGpu->VisibleGGTTOffset + VirtualGpu->VisibleGGTTSize) {
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BAR_IDX0,
+ GTT_OFFSET + Index * GTT_ENTRY_SIZE,
+ 1,
+ &Entry
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed to Set GGTT Entry %lx at index %lx, status %d\n",
+ Entry, Index, Status
+ );
+ }
+ } else if (Index >= VirtualGpu->InvisibleGGTTOffset &&
+ Index < VirtualGpu->InvisibleGGTTOffset + VirtualGpu->InvisibleGGTTSize) {
+ Status = EFI_UNSUPPORTED;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip set GGTT index %lx for invisible GMADR\n", Index
+ );
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip set GGTT index %lx out-of-range, balloon unsupported\n", Index
+ );
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "Set GGTT Entry %lx at index %lx\n", Entry, Index);
+
+ return Status;
+}
+
+EFI_STATUS
+UpdateGGTT (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN EFI_PHYSICAL_ADDRESS GMAddr,
+ IN EFI_PHYSICAL_ADDRESS SysAddr,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ UINTN GttOffset, Index;
+ GTT_PTE_ENTRY Entry;
+
+ if (!IS_ALIGNED(SysAddr, GTT_PAGE_SIZE)) {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed to update GGTT GMADR %lx, SysAddr %lx isn't aligned to 0x%lx, status %d\n",
+ GMAddr, SysAddr, GTT_PAGE_SIZE, Status
+ );
+ goto Done;
+ }
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ GttOffset = (GMAddr - VirtualGpu->GpuMemAddr) >> GTT_PAGE_SHIFT;
+
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "Update GGTT GMADR %lx, SysAddr %lx, Pages 0x%lx\n",
+ GMAddr, SysAddr, Pages
+ );
+ for (Index = 0; Index < Pages; Index++) {
+ Entry = SysAddr + Index * GTT_PAGE_SIZE;
+ Entry |= (GTT_PAGE_PRESENT | GTT_PAGE_READ_WRITE);
+ Entry |= (GTT_PAGE_PWT | GTT_PAGE_PCD);
+ GGTTSetEntry (Private, GttOffset + Index, Entry);
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/Gtt.h b/OvmfPkg/IntelGvtGopDxe/Gtt.h
new file mode 100644
index 000000000000..fc91b7a84a0a
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Gtt.h
@@ -0,0 +1,51 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __GTT_H_
+#define __GTT_H_
+
+#include "Common.h"
+
+typedef UINT64 GTT_PTE_ENTRY;
+
+#define GTT_OFFSET 0x800000
+#define GTT_SIZE 0x800000
+#define GTT_ENTRY_SIZE sizeof(GTT_PTE_ENTRY)
+#define GTT_ENTRY_NUM (GTT_SIZE / GTT_ENTRY_SIZE)
+#define GTT_PAGE_SHIFT 12
+#define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT)
+#define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1))
+#define GTT_PAGE_PRESENT 0x01
+#define GTT_PAGE_READ_WRITE 0x02
+#define GTT_PAGE_PWT 0x08
+#define GTT_PAGE_PCD 0x10
+
+EFI_STATUS
+GGTTGetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ OUT GTT_PTE_ENTRY *Entry
+ );
+
+EFI_STATUS
+GGTTSetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ IN GTT_PTE_ENTRY Entry
+ );
+
+EFI_STATUS
+UpdateGGTT (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN EFI_PHYSICAL_ADDRESS GMAddr,
+ IN EFI_PHYSICAL_ADDRESS SysAddr,
+ IN UINTN Pages
+ );
+
+#endif //__GTT_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf b/OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf
new file mode 100644
index 000000000000..c6e1751e1a22
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf
@@ -0,0 +1,59 @@
+## @file
+# Intel GVT-g Graphics Output Protocol driver
+#
+# Copyright (C) 2021 Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = GvtGopDxe
+ FILE_GUID = 7c2a0c14-2a63-4d08-9c7f-d55691e1cedb
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 2.0
+ ENTRY_POINT = GvtGopEntryPoint
+
+[Sources]
+ Common.h
+ DebugHelper.h
+ Display.c
+ Display.h
+ GopDriver.c
+ GpuReg.c
+ GpuReg.h
+ Gtt.c
+ Gtt.h
+ VirtualGpu.h
+ VirtualGpu.c
+ VbeShim.c
+ VbeShim.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ FrameBufferBltLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ PcdLib
+ PciLib
+ QemuFwCfgLib
+
+[Protocols]
+ gEfiGraphicsOutputProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.asm b/OvmfPkg/IntelGvtGopDxe/VbeShim.asm
new file mode 100644
index 000000000000..43a44362b794
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.asm
@@ -0,0 +1,343 @@
+;------------------------------------------------------------------------------
+; @file
+; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's buggy,
+; default VGA driver to switch to 1024x768x32.
+;
+; Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+; Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+; Copyright (C) 2015, Nahanni Systems, Inc.
+; Copyright (C) 2014, Red Hat, Inc.
+; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+; enable this macro for debug messages
+%define DEBUG
+
+%macro DebugLog 1
+%ifdef DEBUG
+ push si
+ mov si, %1
+ call PrintStringSi
+ pop si
+%endif
+%endmacro
+
+
+BITS 16
+ORG 0
+
+VbeInfo:
+TIMES 256 nop
+
+VbeModeInfo:
+VbeMode1:
+TIMES 50 nop
+VbeMode2:
+TIMES 50 nop
+VbeMode3:
+TIMES 50 nop
+VbeMode4:
+TIMES 50 nop
+TIMES 56 nop ; filler for 256 bytes
+
+Handler:
+ cmp ax, 0x4f00
+ je GetInfo
+ cmp ax, 0x4f01
+ je GetModeInfo
+ cmp ax, 0x4f02
+ je SetMode
+ cmp ax, 0x4f03
+ je GetMode
+ cmp ax, 0x4f10
+ je GetPmCapabilities
+ cmp ax, 0x4f15
+ je ReadEdid
+ cmp ah, 0x00
+ je SetModeLegacy
+ DebugLog StrUnkownFunction
+Hang:
+ jmp Hang
+
+
+GetInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetInfo
+
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, VbeInfo
+ ; source (ds:si) set now
+
+ mov cx, 256
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+GetModeInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetModeInfo
+
+ and cx, ~0x4000 ; clear potentially set LFB bit in mode number
+
+ cmp cx, 0x013f
+ je gKnownMode1
+ cmp cx, 0x0140
+ je gKnownMode2
+ cmp cx, 0x0141
+ je gKnownMode3
+
+ DebugLog StrUnkownMode
+ jmp Hang
+gKnownMode1:
+ DebugLog StrMode1
+ mov si, VbeMode1
+ jmp CopyModeInfo
+gKnownMode2:
+ DebugLog StrMode2
+ mov si, VbeMode2
+ jmp CopyModeInfo
+gKnownMode3:
+ DebugLog StrMode3
+ mov si, VbeMode3
+ jmp CopyModeInfo
+gKnownMode4:
+ DebugLog StrMode4
+ mov si, VbeMode4
+ jmp CopyModeInfo
+
+CopyModeInfo:
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ ;mov si, VbeModeInfo
+ ; source (ds:si) set now
+
+ ;mov cx, 256
+ mov cx, 50
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+SetMode:
+ push dx
+ push ax
+
+ DebugLog StrEnterSetMode
+
+ and bx, ~0x4000 ; clear potentially set LFB bit in mode number
+ cmp bx, 0x013f
+ je KnownMode1
+ cmp bx, 0x0140
+ je KnownMode2
+ cmp bx, 0x0141
+ je KnownMode3
+ DebugLog StrUnkownMode
+ jmp Hang
+KnownMode1:
+ DebugLog StrMode1
+ jmp SetModeDone
+KnownMode2:
+ DebugLog StrMode2
+ jmp SetModeDone
+KnownMode3:
+ DebugLog StrMode3
+ jmp SetModeDone
+KnownMode4:
+ DebugLog StrMode4
+
+SetModeDone:
+ mov [CurMode], bl
+ mov [CurMode+1], bh
+ pop ax
+ pop dx
+ jmp Success
+
+
+GetMode:
+ DebugLog StrEnterGetMode
+ mov bl, [CurMode]
+ mov bh, [CurMode+1]
+ jmp Success
+
+
+GetPmCapabilities:
+ DebugLog StrGetPmCapabilities
+ mov bx, 0x0080
+ jmp Success
+
+
+ReadEdid:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrReadEdid
+
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, Edid
+ ; source (ds:si) set now
+
+ mov cx, 128
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+SetModeLegacy:
+ DebugLog StrEnterSetModeLegacy
+
+ cmp al, 0x03
+ je sKnownMode3
+ cmp al, 0x12
+ je sKnownMode4
+ DebugLog StrUnkownMode
+ jmp Hang
+sKnownMode3:
+ DebugLog StrLegacyMode3
+ mov al, 0 ; 0x30
+ jmp SetModeLegacyDone
+sKnownMode4:
+ mov al, 0 ;0x20
+SetModeLegacyDone:
+ DebugLog StrExitSuccess
+ iret
+
+
+Success:
+ DebugLog StrExitSuccess
+ mov ax, 0x004f
+ iret
+
+
+Unsupported:
+ DebugLog StrExitUnsupported
+ mov ax, 0x024f
+ iret
+
+
+%ifdef DEBUG
+PrintStringSi:
+ pusha
+ push ds ; save original
+ push cs
+ pop ds
+ mov dx, 0x220 ; bhyve debug cons port
+ mov ax, 0
+PrintStringSiLoop:
+ lodsb
+ cmp al, 0
+ je PrintStringSiDone
+ out dx, al
+ jmp PrintStringSiLoop
+PrintStringSiDone:
+ pop ds ; restore original
+ popa
+ ret
+
+
+StrExitSuccess:
+ db 'vOk', 0x0d, 0x0a, 0
+
+StrExitUnsupported:
+ db 'vUnsupported', 0x0d, 0x0a, 0
+
+StrUnkownFunction:
+ db 'vUnknown Function', 0x0d, 0x0a, 0
+
+StrEnterGetInfo:
+ db 'vGetInfo', 0x0d, 0x0a, 0
+
+StrEnterGetModeInfo:
+ db 'vGetModeInfo', 0x0d, 0x0a, 0
+
+StrEnterGetMode:
+ db 'vGetMode', 0x0d, 0x0a, 0
+
+StrEnterSetMode:
+ db 'vSetMode', 0x0d, 0x0a, 0
+
+StrEnterSetModeLegacy:
+ db 'vSetModeLegacy', 0x0d, 0x0a, 0
+
+StrUnkownMode:
+ db 'vUnkown Mode', 0x0d, 0x0a, 0
+
+StrGetPmCapabilities:
+ db 'vGetPmCapabilities', 0x0d, 0x0a, 0
+
+StrReadEdid:
+ db 'vReadEdid', 0x0d, 0x0a, 0
+
+StrLegacyMode3:
+ db 'vLegacyMode3', 0x0d, 0x0a, 0
+
+
+StrMode1:
+ db 'mode_640x480x32', 0x0d, 0x0a, 0
+StrMode2:
+ db 'mode_800x600x32', 0x0d, 0x0a, 0
+StrMode3:
+ db 'mode_1024x768x32', 0x0d, 0x0a, 0
+StrMode4:
+ db 'mode_unused', 0x0d, 0x0a, 0
+%endif
+
+CurMode:
+ db 0x00, 0x00
+
+;
+; EDID stores monitor information. For now, just send back an null item.
+;
+Edid:
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.c b/OvmfPkg/IntelGvtGopDxe/VbeShim.c
new file mode 100644
index 000000000000..8063224d53b4
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.c
@@ -0,0 +1,258 @@
+/** @file
+ Install a fake VGABIOS service handler (real mode Int10h) for the buggy
+ Windows 2008 R2 SP1 UEFI guest.
+
+ The handler is never meant to be directly executed by a VCPU; it's there for
+ the internal real mode emulator of Windows 2008 R2 SP1.
+
+ The code is based on Ralf Brown's Interrupt List:
+ <http://www.cs.cmu.edu/~ralf/files.html>
+ <http://www.ctyme.com/rbrown.htm>
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (C) 2015, Nahanni Systems, Inc.
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include <IndustryStandard/LegacyVgaBios.h>
+#include <Library/PciLib.h>
+#include <Library/PrintLib.h>
+#include "VbeShim.h"
+
+#pragma pack (1)
+typedef struct {
+ UINT16 Offset;
+ UINT16 Segment;
+} IVT_ENTRY;
+#pragma pack ()
+
+//
+// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
+// Advanced Settings dialog. It should be short.
+//
+STATIC CONST CHAR8 mProductRevision[] = "2.0";
+
+#define NUM_VBE_MODES 3
+STATIC CONST UINT16 vbeModeIds[] = {
+ 0x13f, // 640x480x32
+ 0x140, // 800x600x32
+ 0x141 // 1024x768x32
+};
+
+// Modes can be toggled with bit-0
+#define VBE_MODE_ENABLED 0x00BB
+#define VBE_MODE_DISABLED 0x00BA
+
+STATIC VBE2_MODE_INFO vbeModes[] = {
+ { // 0x13f 640x480x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 640*4,
+ // Width, Height..., Vbe3
+ 640, 480, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ },
+ { // 0x140 800x600x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 800*4,
+ // Width, Height..., Vbe3
+ 800, 600, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ },
+ { // 0x141 1024x768x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_ENABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 1024*4,
+ // Width, Height..., Vbe3
+ 1024, 768, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ }
+};
+
+/**
+ Install the VBE Info and VBE Mode Info structures, and the VBE service
+ handler routine in the C segment. Point the real-mode Int10h interrupt vector
+ to the handler. The only advertised mode is 1024x768x32.
+
+ @param[in] CardName Name of the video card to be exposed in the
+ Product Name field of the VBE Info structure.
+ @param[in] FrameBufferBase Guest-physical base address of the video card's
+ frame buffer.
+**/
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ )
+{
+ EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
+ UINTN Segment0Pages;
+ IVT_ENTRY *Int0x10;
+ EFI_STATUS Status;
+ UINTN Pam1Address;
+ UINT8 Pam1;
+ UINTN SegmentCPages;
+ VBE_INFO *VbeInfoFull;
+ VBE_INFO_BASE *VbeInfo;
+ UINT8 *Ptr;
+ UINTN Printed;
+ VBE_MODE_INFO *VbeModeInfo;
+ UINTN i;
+
+ Segment0 = 0x00000;
+ SegmentC = 0xC0000;
+ SegmentF = 0xF0000;
+
+ //
+ // Attempt to cover the real mode IVT with an allocation. This is a UEFI
+ // driver, hence the arch protocols have been installed previously. Among
+ // those, the CPU arch protocol has configured the IDT, so we can overwrite
+ // the IVT used in real mode.
+ //
+ // The allocation request may fail, eg. if LegacyBiosDxe has already run.
+ //
+ Segment0Pages = 1;
+ Int0x10 = (IVT_ENTRY *)(UINTN)Segment0 + 0x10;
+ Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode,
+ Segment0Pages, &Segment0);
+
+ if (EFI_ERROR (Status)) {
+ EFI_PHYSICAL_ADDRESS Handler;
+
+ //
+ // Check if a video BIOS handler has been installed previously -- we
+ // shouldn't override a real video BIOS with our shim, nor our own shim if
+ // it's already present.
+ //
+ Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
+ if (Handler >= SegmentC && Handler < SegmentF) {
+ DEBUG ((DEBUG_VERBOSE, "%a: Video BIOS handler found at %04x:%04x\n",
+ __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+ return;
+ }
+
+ //
+ // Otherwise we'll overwrite the Int10h vector, even though we may not own
+ // the page at zero.
+ //
+ DEBUG ((DEBUG_VERBOSE, "%a: failed to allocate page at zero: %r\n",
+ __FUNCTION__, Status));
+ } else {
+ //
+ // We managed to allocate the page at zero. SVN r14218 guarantees that it
+ // is NUL-filled.
+ //
+ ASSERT (Int0x10->Segment == 0x0000);
+ ASSERT (Int0x10->Offset == 0x0000);
+ }
+
+ //
+ // Put the shim in place first.
+ //
+ Pam1Address = PCI_LIB_ADDRESS (0, 0, 0, 0x5A);
+ //
+ // low nibble covers 0xC0000 to 0xC3FFF
+ // high nibble covers 0xC4000 to 0xC7FFF
+ // bit1 in each nibble is Write Enable
+ // bit0 in each nibble is Read Enable
+ //
+ Pam1 = PciRead8 (Pam1Address);
+ PciWrite8 (Pam1Address, Pam1 | (BIT1 | BIT0));
+
+ //
+ // We never added memory space durig PEI or DXE for the C segment, so we
+ // don't need to (and can't) allocate from there. Also, guest operating
+ // systems will see a hole in the UEFI memory map there.
+ //
+ SegmentCPages = 4;
+
+ ASSERT (sizeof gVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
+ CopyMem ((VOID *)(UINTN)SegmentC, gVbeShim, sizeof gVbeShim);
+
+ //
+ // Fill in the VBE INFO structure.
+ //
+ VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
+ VbeInfo = &VbeInfoFull->Base;
+ Ptr = VbeInfoFull->Buffer;
+
+ CopyMem (VbeInfo->Signature, "VESA", 4);
+ VbeInfo->VesaVersion = 0x0200;
+
+ VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, "FBSD", 5);
+ Ptr += 5;
+
+ VbeInfo->Capabilities = BIT1 | BIT0; // DAC can be switched into 8-bit mode
+
+ VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ for (i = 0; i < NUM_VBE_MODES; i ++) {
+ *(UINT16*)Ptr = vbeModeIds[i]; // mode number
+ Ptr += 2;
+ }
+ *(UINT16*)Ptr = 0xFFFF; // mode list terminator
+ Ptr += 2;
+
+ VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
+ VbeInfo->OemSoftwareVersion = 0x0200;
+
+ VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, "FBSD", 5);
+ Ptr += 5;
+
+ VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ Printed = AsciiSPrint ((CHAR8 *)Ptr,
+ sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s",
+ CardName);
+ Ptr += Printed + 1;
+
+ VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
+ Ptr += sizeof mProductRevision;
+
+ ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
+ ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
+
+ //
+ // Fill in the VBE MODE INFO structure list
+ //
+ VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
+ Ptr = (UINT8 *)VbeModeInfo;
+ for (i = 0; i < NUM_VBE_MODES; i++) {
+ vbeModes[i].LfbAddress = (UINT32)FrameBufferBase;
+ CopyMem (Ptr, &vbeModes[i], 0x32);
+ Ptr += 0x32;
+ }
+
+ ZeroMem (Ptr, 56); // Clear remaining bytes
+
+ //
+ // Clear Write Enable (bit1), keep Read Enable (bit0) set
+ //
+ PciWrite8 (Pam1Address, (Pam1 & ~BIT1) | BIT0);
+
+ //
+ // Second, point the Int10h vector at the shim.
+ //
+ Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
+ Int0x10->Offset = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
+
+ DEBUG ((DEBUG_INFO, "%a: VBE shim installed to %x:%x\n",
+ __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.h b/OvmfPkg/IntelGvtGopDxe/VbeShim.h
new file mode 100644
index 000000000000..601b1465cbe5
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.h
@@ -0,0 +1,912 @@
+//
+// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
+//
+#ifndef _VBE_SHIM_H_
+#define _VBE_SHIM_H_
+STATIC CONST UINT8 gVbeShim[] = {
+ /* 00000000 nop */ 0x90,
+ /* 00000001 nop */ 0x90,
+ /* 00000002 nop */ 0x90,
+ /* 00000003 nop */ 0x90,
+ /* 00000004 nop */ 0x90,
+ /* 00000005 nop */ 0x90,
+ /* 00000006 nop */ 0x90,
+ /* 00000007 nop */ 0x90,
+ /* 00000008 nop */ 0x90,
+ /* 00000009 nop */ 0x90,
+ /* 0000000A nop */ 0x90,
+ /* 0000000B nop */ 0x90,
+ /* 0000000C nop */ 0x90,
+ /* 0000000D nop */ 0x90,
+ /* 0000000E nop */ 0x90,
+ /* 0000000F nop */ 0x90,
+ /* 00000010 nop */ 0x90,
+ /* 00000011 nop */ 0x90,
+ /* 00000012 nop */ 0x90,
+ /* 00000013 nop */ 0x90,
+ /* 00000014 nop */ 0x90,
+ /* 00000015 nop */ 0x90,
+ /* 00000016 nop */ 0x90,
+ /* 00000017 nop */ 0x90,
+ /* 00000018 nop */ 0x90,
+ /* 00000019 nop */ 0x90,
+ /* 0000001A nop */ 0x90,
+ /* 0000001B nop */ 0x90,
+ /* 0000001C nop */ 0x90,
+ /* 0000001D nop */ 0x90,
+ /* 0000001E nop */ 0x90,
+ /* 0000001F nop */ 0x90,
+ /* 00000020 nop */ 0x90,
+ /* 00000021 nop */ 0x90,
+ /* 00000022 nop */ 0x90,
+ /* 00000023 nop */ 0x90,
+ /* 00000024 nop */ 0x90,
+ /* 00000025 nop */ 0x90,
+ /* 00000026 nop */ 0x90,
+ /* 00000027 nop */ 0x90,
+ /* 00000028 nop */ 0x90,
+ /* 00000029 nop */ 0x90,
+ /* 0000002A nop */ 0x90,
+ /* 0000002B nop */ 0x90,
+ /* 0000002C nop */ 0x90,
+ /* 0000002D nop */ 0x90,
+ /* 0000002E nop */ 0x90,
+ /* 0000002F nop */ 0x90,
+ /* 00000030 nop */ 0x90,
+ /* 00000031 nop */ 0x90,
+ /* 00000032 nop */ 0x90,
+ /* 00000033 nop */ 0x90,
+ /* 00000034 nop */ 0x90,
+ /* 00000035 nop */ 0x90,
+ /* 00000036 nop */ 0x90,
+ /* 00000037 nop */ 0x90,
+ /* 00000038 nop */ 0x90,
+ /* 00000039 nop */ 0x90,
+ /* 0000003A nop */ 0x90,
+ /* 0000003B nop */ 0x90,
+ /* 0000003C nop */ 0x90,
+ /* 0000003D nop */ 0x90,
+ /* 0000003E nop */ 0x90,
+ /* 0000003F nop */ 0x90,
+ /* 00000040 nop */ 0x90,
+ /* 00000041 nop */ 0x90,
+ /* 00000042 nop */ 0x90,
+ /* 00000043 nop */ 0x90,
+ /* 00000044 nop */ 0x90,
+ /* 00000045 nop */ 0x90,
+ /* 00000046 nop */ 0x90,
+ /* 00000047 nop */ 0x90,
+ /* 00000048 nop */ 0x90,
+ /* 00000049 nop */ 0x90,
+ /* 0000004A nop */ 0x90,
+ /* 0000004B nop */ 0x90,
+ /* 0000004C nop */ 0x90,
+ /* 0000004D nop */ 0x90,
+ /* 0000004E nop */ 0x90,
+ /* 0000004F nop */ 0x90,
+ /* 00000050 nop */ 0x90,
+ /* 00000051 nop */ 0x90,
+ /* 00000052 nop */ 0x90,
+ /* 00000053 nop */ 0x90,
+ /* 00000054 nop */ 0x90,
+ /* 00000055 nop */ 0x90,
+ /* 00000056 nop */ 0x90,
+ /* 00000057 nop */ 0x90,
+ /* 00000058 nop */ 0x90,
+ /* 00000059 nop */ 0x90,
+ /* 0000005A nop */ 0x90,
+ /* 0000005B nop */ 0x90,
+ /* 0000005C nop */ 0x90,
+ /* 0000005D nop */ 0x90,
+ /* 0000005E nop */ 0x90,
+ /* 0000005F nop */ 0x90,
+ /* 00000060 nop */ 0x90,
+ /* 00000061 nop */ 0x90,
+ /* 00000062 nop */ 0x90,
+ /* 00000063 nop */ 0x90,
+ /* 00000064 nop */ 0x90,
+ /* 00000065 nop */ 0x90,
+ /* 00000066 nop */ 0x90,
+ /* 00000067 nop */ 0x90,
+ /* 00000068 nop */ 0x90,
+ /* 00000069 nop */ 0x90,
+ /* 0000006A nop */ 0x90,
+ /* 0000006B nop */ 0x90,
+ /* 0000006C nop */ 0x90,
+ /* 0000006D nop */ 0x90,
+ /* 0000006E nop */ 0x90,
+ /* 0000006F nop */ 0x90,
+ /* 00000070 nop */ 0x90,
+ /* 00000071 nop */ 0x90,
+ /* 00000072 nop */ 0x90,
+ /* 00000073 nop */ 0x90,
+ /* 00000074 nop */ 0x90,
+ /* 00000075 nop */ 0x90,
+ /* 00000076 nop */ 0x90,
+ /* 00000077 nop */ 0x90,
+ /* 00000078 nop */ 0x90,
+ /* 00000079 nop */ 0x90,
+ /* 0000007A nop */ 0x90,
+ /* 0000007B nop */ 0x90,
+ /* 0000007C nop */ 0x90,
+ /* 0000007D nop */ 0x90,
+ /* 0000007E nop */ 0x90,
+ /* 0000007F nop */ 0x90,
+ /* 00000080 nop */ 0x90,
+ /* 00000081 nop */ 0x90,
+ /* 00000082 nop */ 0x90,
+ /* 00000083 nop */ 0x90,
+ /* 00000084 nop */ 0x90,
+ /* 00000085 nop */ 0x90,
+ /* 00000086 nop */ 0x90,
+ /* 00000087 nop */ 0x90,
+ /* 00000088 nop */ 0x90,
+ /* 00000089 nop */ 0x90,
+ /* 0000008A nop */ 0x90,
+ /* 0000008B nop */ 0x90,
+ /* 0000008C nop */ 0x90,
+ /* 0000008D nop */ 0x90,
+ /* 0000008E nop */ 0x90,
+ /* 0000008F nop */ 0x90,
+ /* 00000090 nop */ 0x90,
+ /* 00000091 nop */ 0x90,
+ /* 00000092 nop */ 0x90,
+ /* 00000093 nop */ 0x90,
+ /* 00000094 nop */ 0x90,
+ /* 00000095 nop */ 0x90,
+ /* 00000096 nop */ 0x90,
+ /* 00000097 nop */ 0x90,
+ /* 00000098 nop */ 0x90,
+ /* 00000099 nop */ 0x90,
+ /* 0000009A nop */ 0x90,
+ /* 0000009B nop */ 0x90,
+ /* 0000009C nop */ 0x90,
+ /* 0000009D nop */ 0x90,
+ /* 0000009E nop */ 0x90,
+ /* 0000009F nop */ 0x90,
+ /* 000000A0 nop */ 0x90,
+ /* 000000A1 nop */ 0x90,
+ /* 000000A2 nop */ 0x90,
+ /* 000000A3 nop */ 0x90,
+ /* 000000A4 nop */ 0x90,
+ /* 000000A5 nop */ 0x90,
+ /* 000000A6 nop */ 0x90,
+ /* 000000A7 nop */ 0x90,
+ /* 000000A8 nop */ 0x90,
+ /* 000000A9 nop */ 0x90,
+ /* 000000AA nop */ 0x90,
+ /* 000000AB nop */ 0x90,
+ /* 000000AC nop */ 0x90,
+ /* 000000AD nop */ 0x90,
+ /* 000000AE nop */ 0x90,
+ /* 000000AF nop */ 0x90,
+ /* 000000B0 nop */ 0x90,
+ /* 000000B1 nop */ 0x90,
+ /* 000000B2 nop */ 0x90,
+ /* 000000B3 nop */ 0x90,
+ /* 000000B4 nop */ 0x90,
+ /* 000000B5 nop */ 0x90,
+ /* 000000B6 nop */ 0x90,
+ /* 000000B7 nop */ 0x90,
+ /* 000000B8 nop */ 0x90,
+ /* 000000B9 nop */ 0x90,
+ /* 000000BA nop */ 0x90,
+ /* 000000BB nop */ 0x90,
+ /* 000000BC nop */ 0x90,
+ /* 000000BD nop */ 0x90,
+ /* 000000BE nop */ 0x90,
+ /* 000000BF nop */ 0x90,
+ /* 000000C0 nop */ 0x90,
+ /* 000000C1 nop */ 0x90,
+ /* 000000C2 nop */ 0x90,
+ /* 000000C3 nop */ 0x90,
+ /* 000000C4 nop */ 0x90,
+ /* 000000C5 nop */ 0x90,
+ /* 000000C6 nop */ 0x90,
+ /* 000000C7 nop */ 0x90,
+ /* 000000C8 nop */ 0x90,
+ /* 000000C9 nop */ 0x90,
+ /* 000000CA nop */ 0x90,
+ /* 000000CB nop */ 0x90,
+ /* 000000CC nop */ 0x90,
+ /* 000000CD nop */ 0x90,
+ /* 000000CE nop */ 0x90,
+ /* 000000CF nop */ 0x90,
+ /* 000000D0 nop */ 0x90,
+ /* 000000D1 nop */ 0x90,
+ /* 000000D2 nop */ 0x90,
+ /* 000000D3 nop */ 0x90,
+ /* 000000D4 nop */ 0x90,
+ /* 000000D5 nop */ 0x90,
+ /* 000000D6 nop */ 0x90,
+ /* 000000D7 nop */ 0x90,
+ /* 000000D8 nop */ 0x90,
+ /* 000000D9 nop */ 0x90,
+ /* 000000DA nop */ 0x90,
+ /* 000000DB nop */ 0x90,
+ /* 000000DC nop */ 0x90,
+ /* 000000DD nop */ 0x90,
+ /* 000000DE nop */ 0x90,
+ /* 000000DF nop */ 0x90,
+ /* 000000E0 nop */ 0x90,
+ /* 000000E1 nop */ 0x90,
+ /* 000000E2 nop */ 0x90,
+ /* 000000E3 nop */ 0x90,
+ /* 000000E4 nop */ 0x90,
+ /* 000000E5 nop */ 0x90,
+ /* 000000E6 nop */ 0x90,
+ /* 000000E7 nop */ 0x90,
+ /* 000000E8 nop */ 0x90,
+ /* 000000E9 nop */ 0x90,
+ /* 000000EA nop */ 0x90,
+ /* 000000EB nop */ 0x90,
+ /* 000000EC nop */ 0x90,
+ /* 000000ED nop */ 0x90,
+ /* 000000EE nop */ 0x90,
+ /* 000000EF nop */ 0x90,
+ /* 000000F0 nop */ 0x90,
+ /* 000000F1 nop */ 0x90,
+ /* 000000F2 nop */ 0x90,
+ /* 000000F3 nop */ 0x90,
+ /* 000000F4 nop */ 0x90,
+ /* 000000F5 nop */ 0x90,
+ /* 000000F6 nop */ 0x90,
+ /* 000000F7 nop */ 0x90,
+ /* 000000F8 nop */ 0x90,
+ /* 000000F9 nop */ 0x90,
+ /* 000000FA nop */ 0x90,
+ /* 000000FB nop */ 0x90,
+ /* 000000FC nop */ 0x90,
+ /* 000000FD nop */ 0x90,
+ /* 000000FE nop */ 0x90,
+ /* 000000FF nop */ 0x90,
+ /* 00000100 nop */ 0x90,
+ /* 00000101 nop */ 0x90,
+ /* 00000102 nop */ 0x90,
+ /* 00000103 nop */ 0x90,
+ /* 00000104 nop */ 0x90,
+ /* 00000105 nop */ 0x90,
+ /* 00000106 nop */ 0x90,
+ /* 00000107 nop */ 0x90,
+ /* 00000108 nop */ 0x90,
+ /* 00000109 nop */ 0x90,
+ /* 0000010A nop */ 0x90,
+ /* 0000010B nop */ 0x90,
+ /* 0000010C nop */ 0x90,
+ /* 0000010D nop */ 0x90,
+ /* 0000010E nop */ 0x90,
+ /* 0000010F nop */ 0x90,
+ /* 00000110 nop */ 0x90,
+ /* 00000111 nop */ 0x90,
+ /* 00000112 nop */ 0x90,
+ /* 00000113 nop */ 0x90,
+ /* 00000114 nop */ 0x90,
+ /* 00000115 nop */ 0x90,
+ /* 00000116 nop */ 0x90,
+ /* 00000117 nop */ 0x90,
+ /* 00000118 nop */ 0x90,
+ /* 00000119 nop */ 0x90,
+ /* 0000011A nop */ 0x90,
+ /* 0000011B nop */ 0x90,
+ /* 0000011C nop */ 0x90,
+ /* 0000011D nop */ 0x90,
+ /* 0000011E nop */ 0x90,
+ /* 0000011F nop */ 0x90,
+ /* 00000120 nop */ 0x90,
+ /* 00000121 nop */ 0x90,
+ /* 00000122 nop */ 0x90,
+ /* 00000123 nop */ 0x90,
+ /* 00000124 nop */ 0x90,
+ /* 00000125 nop */ 0x90,
+ /* 00000126 nop */ 0x90,
+ /* 00000127 nop */ 0x90,
+ /* 00000128 nop */ 0x90,
+ /* 00000129 nop */ 0x90,
+ /* 0000012A nop */ 0x90,
+ /* 0000012B nop */ 0x90,
+ /* 0000012C nop */ 0x90,
+ /* 0000012D nop */ 0x90,
+ /* 0000012E nop */ 0x90,
+ /* 0000012F nop */ 0x90,
+ /* 00000130 nop */ 0x90,
+ /* 00000131 nop */ 0x90,
+ /* 00000132 nop */ 0x90,
+ /* 00000133 nop */ 0x90,
+ /* 00000134 nop */ 0x90,
+ /* 00000135 nop */ 0x90,
+ /* 00000136 nop */ 0x90,
+ /* 00000137 nop */ 0x90,
+ /* 00000138 nop */ 0x90,
+ /* 00000139 nop */ 0x90,
+ /* 0000013A nop */ 0x90,
+ /* 0000013B nop */ 0x90,
+ /* 0000013C nop */ 0x90,
+ /* 0000013D nop */ 0x90,
+ /* 0000013E nop */ 0x90,
+ /* 0000013F nop */ 0x90,
+ /* 00000140 nop */ 0x90,
+ /* 00000141 nop */ 0x90,
+ /* 00000142 nop */ 0x90,
+ /* 00000143 nop */ 0x90,
+ /* 00000144 nop */ 0x90,
+ /* 00000145 nop */ 0x90,
+ /* 00000146 nop */ 0x90,
+ /* 00000147 nop */ 0x90,
+ /* 00000148 nop */ 0x90,
+ /* 00000149 nop */ 0x90,
+ /* 0000014A nop */ 0x90,
+ /* 0000014B nop */ 0x90,
+ /* 0000014C nop */ 0x90,
+ /* 0000014D nop */ 0x90,
+ /* 0000014E nop */ 0x90,
+ /* 0000014F nop */ 0x90,
+ /* 00000150 nop */ 0x90,
+ /* 00000151 nop */ 0x90,
+ /* 00000152 nop */ 0x90,
+ /* 00000153 nop */ 0x90,
+ /* 00000154 nop */ 0x90,
+ /* 00000155 nop */ 0x90,
+ /* 00000156 nop */ 0x90,
+ /* 00000157 nop */ 0x90,
+ /* 00000158 nop */ 0x90,
+ /* 00000159 nop */ 0x90,
+ /* 0000015A nop */ 0x90,
+ /* 0000015B nop */ 0x90,
+ /* 0000015C nop */ 0x90,
+ /* 0000015D nop */ 0x90,
+ /* 0000015E nop */ 0x90,
+ /* 0000015F nop */ 0x90,
+ /* 00000160 nop */ 0x90,
+ /* 00000161 nop */ 0x90,
+ /* 00000162 nop */ 0x90,
+ /* 00000163 nop */ 0x90,
+ /* 00000164 nop */ 0x90,
+ /* 00000165 nop */ 0x90,
+ /* 00000166 nop */ 0x90,
+ /* 00000167 nop */ 0x90,
+ /* 00000168 nop */ 0x90,
+ /* 00000169 nop */ 0x90,
+ /* 0000016A nop */ 0x90,
+ /* 0000016B nop */ 0x90,
+ /* 0000016C nop */ 0x90,
+ /* 0000016D nop */ 0x90,
+ /* 0000016E nop */ 0x90,
+ /* 0000016F nop */ 0x90,
+ /* 00000170 nop */ 0x90,
+ /* 00000171 nop */ 0x90,
+ /* 00000172 nop */ 0x90,
+ /* 00000173 nop */ 0x90,
+ /* 00000174 nop */ 0x90,
+ /* 00000175 nop */ 0x90,
+ /* 00000176 nop */ 0x90,
+ /* 00000177 nop */ 0x90,
+ /* 00000178 nop */ 0x90,
+ /* 00000179 nop */ 0x90,
+ /* 0000017A nop */ 0x90,
+ /* 0000017B nop */ 0x90,
+ /* 0000017C nop */ 0x90,
+ /* 0000017D nop */ 0x90,
+ /* 0000017E nop */ 0x90,
+ /* 0000017F nop */ 0x90,
+ /* 00000180 nop */ 0x90,
+ /* 00000181 nop */ 0x90,
+ /* 00000182 nop */ 0x90,
+ /* 00000183 nop */ 0x90,
+ /* 00000184 nop */ 0x90,
+ /* 00000185 nop */ 0x90,
+ /* 00000186 nop */ 0x90,
+ /* 00000187 nop */ 0x90,
+ /* 00000188 nop */ 0x90,
+ /* 00000189 nop */ 0x90,
+ /* 0000018A nop */ 0x90,
+ /* 0000018B nop */ 0x90,
+ /* 0000018C nop */ 0x90,
+ /* 0000018D nop */ 0x90,
+ /* 0000018E nop */ 0x90,
+ /* 0000018F nop */ 0x90,
+ /* 00000190 nop */ 0x90,
+ /* 00000191 nop */ 0x90,
+ /* 00000192 nop */ 0x90,
+ /* 00000193 nop */ 0x90,
+ /* 00000194 nop */ 0x90,
+ /* 00000195 nop */ 0x90,
+ /* 00000196 nop */ 0x90,
+ /* 00000197 nop */ 0x90,
+ /* 00000198 nop */ 0x90,
+ /* 00000199 nop */ 0x90,
+ /* 0000019A nop */ 0x90,
+ /* 0000019B nop */ 0x90,
+ /* 0000019C nop */ 0x90,
+ /* 0000019D nop */ 0x90,
+ /* 0000019E nop */ 0x90,
+ /* 0000019F nop */ 0x90,
+ /* 000001A0 nop */ 0x90,
+ /* 000001A1 nop */ 0x90,
+ /* 000001A2 nop */ 0x90,
+ /* 000001A3 nop */ 0x90,
+ /* 000001A4 nop */ 0x90,
+ /* 000001A5 nop */ 0x90,
+ /* 000001A6 nop */ 0x90,
+ /* 000001A7 nop */ 0x90,
+ /* 000001A8 nop */ 0x90,
+ /* 000001A9 nop */ 0x90,
+ /* 000001AA nop */ 0x90,
+ /* 000001AB nop */ 0x90,
+ /* 000001AC nop */ 0x90,
+ /* 000001AD nop */ 0x90,
+ /* 000001AE nop */ 0x90,
+ /* 000001AF nop */ 0x90,
+ /* 000001B0 nop */ 0x90,
+ /* 000001B1 nop */ 0x90,
+ /* 000001B2 nop */ 0x90,
+ /* 000001B3 nop */ 0x90,
+ /* 000001B4 nop */ 0x90,
+ /* 000001B5 nop */ 0x90,
+ /* 000001B6 nop */ 0x90,
+ /* 000001B7 nop */ 0x90,
+ /* 000001B8 nop */ 0x90,
+ /* 000001B9 nop */ 0x90,
+ /* 000001BA nop */ 0x90,
+ /* 000001BB nop */ 0x90,
+ /* 000001BC nop */ 0x90,
+ /* 000001BD nop */ 0x90,
+ /* 000001BE nop */ 0x90,
+ /* 000001BF nop */ 0x90,
+ /* 000001C0 nop */ 0x90,
+ /* 000001C1 nop */ 0x90,
+ /* 000001C2 nop */ 0x90,
+ /* 000001C3 nop */ 0x90,
+ /* 000001C4 nop */ 0x90,
+ /* 000001C5 nop */ 0x90,
+ /* 000001C6 nop */ 0x90,
+ /* 000001C7 nop */ 0x90,
+ /* 000001C8 nop */ 0x90,
+ /* 000001C9 nop */ 0x90,
+ /* 000001CA nop */ 0x90,
+ /* 000001CB nop */ 0x90,
+ /* 000001CC nop */ 0x90,
+ /* 000001CD nop */ 0x90,
+ /* 000001CE nop */ 0x90,
+ /* 000001CF nop */ 0x90,
+ /* 000001D0 nop */ 0x90,
+ /* 000001D1 nop */ 0x90,
+ /* 000001D2 nop */ 0x90,
+ /* 000001D3 nop */ 0x90,
+ /* 000001D4 nop */ 0x90,
+ /* 000001D5 nop */ 0x90,
+ /* 000001D6 nop */ 0x90,
+ /* 000001D7 nop */ 0x90,
+ /* 000001D8 nop */ 0x90,
+ /* 000001D9 nop */ 0x90,
+ /* 000001DA nop */ 0x90,
+ /* 000001DB nop */ 0x90,
+ /* 000001DC nop */ 0x90,
+ /* 000001DD nop */ 0x90,
+ /* 000001DE nop */ 0x90,
+ /* 000001DF nop */ 0x90,
+ /* 000001E0 nop */ 0x90,
+ /* 000001E1 nop */ 0x90,
+ /* 000001E2 nop */ 0x90,
+ /* 000001E3 nop */ 0x90,
+ /* 000001E4 nop */ 0x90,
+ /* 000001E5 nop */ 0x90,
+ /* 000001E6 nop */ 0x90,
+ /* 000001E7 nop */ 0x90,
+ /* 000001E8 nop */ 0x90,
+ /* 000001E9 nop */ 0x90,
+ /* 000001EA nop */ 0x90,
+ /* 000001EB nop */ 0x90,
+ /* 000001EC nop */ 0x90,
+ /* 000001ED nop */ 0x90,
+ /* 000001EE nop */ 0x90,
+ /* 000001EF nop */ 0x90,
+ /* 000001F0 nop */ 0x90,
+ /* 000001F1 nop */ 0x90,
+ /* 000001F2 nop */ 0x90,
+ /* 000001F3 nop */ 0x90,
+ /* 000001F4 nop */ 0x90,
+ /* 000001F5 nop */ 0x90,
+ /* 000001F6 nop */ 0x90,
+ /* 000001F7 nop */ 0x90,
+ /* 000001F8 nop */ 0x90,
+ /* 000001F9 nop */ 0x90,
+ /* 000001FA nop */ 0x90,
+ /* 000001FB nop */ 0x90,
+ /* 000001FC nop */ 0x90,
+ /* 000001FD nop */ 0x90,
+ /* 000001FE nop */ 0x90,
+ /* 000001FF nop */ 0x90,
+ /* 00000200 cmp ax,0x4f00 */ 0x3D, 0x00, 0x4F,
+ /* 00000203 jz 0x237 */ 0x74, 0x32,
+ /* 00000205 cmp ax,0x4f01 */ 0x3D, 0x01, 0x4F,
+ /* 00000208 jz 0x257 */ 0x74, 0x4D,
+ /* 0000020A cmp ax,0x4f02 */ 0x3D, 0x02, 0x4F,
+ /* 0000020D jz near 0x2c8 */ 0x0F, 0x84, 0xB7, 0x00,
+ /* 00000211 cmp ax,0x4f03 */ 0x3D, 0x03, 0x4F,
+ /* 00000214 jz near 0x325 */ 0x0F, 0x84, 0x0D, 0x01,
+ /* 00000218 cmp ax,0x4f10 */ 0x3D, 0x10, 0x4F,
+ /* 0000021B jz near 0x337 */ 0x0F, 0x84, 0x18, 0x01,
+ /* 0000021F cmp ax,0x4f15 */ 0x3D, 0x15, 0x4F,
+ /* 00000222 jz near 0x344 */ 0x0F, 0x84, 0x1E, 0x01,
+ /* 00000226 cmp ah,0x0 */ 0x80, 0xFC, 0x00,
+ /* 00000229 jz near 0x363 */ 0x0F, 0x84, 0x36, 0x01,
+ /* 0000022D push si */ 0x56,
+ /* 0000022E mov si,0x3d7 */ 0xBE, 0xD7, 0x03,
+ /* 00000231 call 0x3ad */ 0xE8, 0x79, 0x01,
+ /* 00000234 pop si */ 0x5E,
+ /* 00000235 jmp short 0x235 */ 0xEB, 0xFE,
+ /* 00000237 push es */ 0x06,
+ /* 00000238 push di */ 0x57,
+ /* 00000239 push ds */ 0x1E,
+ /* 0000023A push si */ 0x56,
+ /* 0000023B push cx */ 0x51,
+ /* 0000023C push si */ 0x56,
+ /* 0000023D mov si,0x3eb */ 0xBE, 0xEB, 0x03,
+ /* 00000240 call 0x3ad */ 0xE8, 0x6A, 0x01,
+ /* 00000243 pop si */ 0x5E,
+ /* 00000244 push cs */ 0x0E,
+ /* 00000245 pop ds */ 0x1F,
+ /* 00000246 mov si,0x0 */ 0xBE, 0x00, 0x00,
+ /* 00000249 mov cx,0x100 */ 0xB9, 0x00, 0x01,
+ /* 0000024C cld */ 0xFC,
+ /* 0000024D rep movsb */ 0xF3, 0xA4,
+ /* 0000024F pop cx */ 0x59,
+ /* 00000250 pop si */ 0x5E,
+ /* 00000251 pop ds */ 0x1F,
+ /* 00000252 pop di */ 0x5F,
+ /* 00000253 pop es */ 0x07,
+ /* 00000254 jmp 0x395 */ 0xE9, 0x3E, 0x01,
+ /* 00000257 push es */ 0x06,
+ /* 00000258 push di */ 0x57,
+ /* 00000259 push ds */ 0x1E,
+ /* 0000025A push si */ 0x56,
+ /* 0000025B push cx */ 0x51,
+ /* 0000025C push si */ 0x56,
+ /* 0000025D mov si,0x3f6 */ 0xBE, 0xF6, 0x03,
+ /* 00000260 call 0x3ad */ 0xE8, 0x4A, 0x01,
+ /* 00000263 pop si */ 0x5E,
+ /* 00000264 and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
+ /* 00000268 cmp cx,0x13f */ 0x81, 0xF9, 0x3F, 0x01,
+ /* 0000026C jz 0x284 */ 0x74, 0x16,
+ /* 0000026E cmp cx,0x140 */ 0x81, 0xF9, 0x40, 0x01,
+ /* 00000272 jz 0x291 */ 0x74, 0x1D,
+ /* 00000274 cmp cx,0x141 */ 0x81, 0xF9, 0x41, 0x01,
+ /* 00000278 jz 0x29e */ 0x74, 0x24,
+ /* 0000027A push si */ 0x56,
+ /* 0000027B mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 0000027E call 0x3ad */ 0xE8, 0x2C, 0x01,
+ /* 00000281 pop si */ 0x5E,
+ /* 00000282 jmp short 0x235 */ 0xEB, 0xB1,
+ /* 00000284 push si */ 0x56,
+ /* 00000285 mov si,0x46b */ 0xBE, 0x6B, 0x04,
+ /* 00000288 call 0x3ad */ 0xE8, 0x22, 0x01,
+ /* 0000028B pop si */ 0x5E,
+ /* 0000028C mov si,0x100 */ 0xBE, 0x00, 0x01,
+ /* 0000028F jmp short 0x2b8 */ 0xEB, 0x27,
+ /* 00000291 push si */ 0x56,
+ /* 00000292 mov si,0x47d */ 0xBE, 0x7D, 0x04,
+ /* 00000295 call 0x3ad */ 0xE8, 0x15, 0x01,
+ /* 00000298 pop si */ 0x5E,
+ /* 00000299 mov si,0x132 */ 0xBE, 0x32, 0x01,
+ /* 0000029C jmp short 0x2b8 */ 0xEB, 0x1A,
+ /* 0000029E push si */ 0x56,
+ /* 0000029F mov si,0x48f */ 0xBE, 0x8F, 0x04,
+ /* 000002A2 call 0x3ad */ 0xE8, 0x08, 0x01,
+ /* 000002A5 pop si */ 0x5E,
+ /* 000002A6 mov si,0x164 */ 0xBE, 0x64, 0x01,
+ /* 000002A9 jmp short 0x2b8 */ 0xEB, 0x0D,
+ /* 000002AB push si */ 0x56,
+ /* 000002AC mov si,0x4a2 */ 0xBE, 0xA2, 0x04,
+ /* 000002AF call 0x3ad */ 0xE8, 0xFB, 0x00,
+ /* 000002B2 pop si */ 0x5E,
+ /* 000002B3 mov si,0x196 */ 0xBE, 0x96, 0x01,
+ /* 000002B6 jmp short 0x2b8 */ 0xEB, 0x00,
+ /* 000002B8 push cs */ 0x0E,
+ /* 000002B9 pop ds */ 0x1F,
+ /* 000002BA mov cx,0x32 */ 0xB9, 0x32, 0x00,
+ /* 000002BD cld */ 0xFC,
+ /* 000002BE rep movsb */ 0xF3, 0xA4,
+ /* 000002C0 pop cx */ 0x59,
+ /* 000002C1 pop si */ 0x5E,
+ /* 000002C2 pop ds */ 0x1F,
+ /* 000002C3 pop di */ 0x5F,
+ /* 000002C4 pop es */ 0x07,
+ /* 000002C5 jmp 0x395 */ 0xE9, 0xCD, 0x00,
+ /* 000002C8 push dx */ 0x52,
+ /* 000002C9 push ax */ 0x50,
+ /* 000002CA push si */ 0x56,
+ /* 000002CB mov si,0x410 */ 0xBE, 0x10, 0x04,
+ /* 000002CE call 0x3ad */ 0xE8, 0xDC, 0x00,
+ /* 000002D1 pop si */ 0x5E,
+ /* 000002D2 and bx,0xbfff */ 0x81, 0xE3, 0xFF, 0xBF,
+ /* 000002D6 cmp bx,0x13f */ 0x81, 0xFB, 0x3F, 0x01,
+ /* 000002DA jz 0x2f3 */ 0x74, 0x17,
+ /* 000002DC cmp bx,0x140 */ 0x81, 0xFB, 0x40, 0x01,
+ /* 000002E0 jz 0x2fd */ 0x74, 0x1B,
+ /* 000002E2 cmp bx,0x141 */ 0x81, 0xFB, 0x41, 0x01,
+ /* 000002E6 jz 0x307 */ 0x74, 0x1F,
+ /* 000002E8 push si */ 0x56,
+ /* 000002E9 mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 000002EC call 0x3ad */ 0xE8, 0xBE, 0x00,
+ /* 000002EF pop si */ 0x5E,
+ /* 000002F0 jmp 0x235 */ 0xE9, 0x42, 0xFF,
+ /* 000002F3 push si */ 0x56,
+ /* 000002F4 mov si,0x46b */ 0xBE, 0x6B, 0x04,
+ /* 000002F7 call 0x3ad */ 0xE8, 0xB3, 0x00,
+ /* 000002FA pop si */ 0x5E,
+ /* 000002FB jmp short 0x319 */ 0xEB, 0x1C,
+ /* 000002FD push si */ 0x56,
+ /* 000002FE mov si,0x47d */ 0xBE, 0x7D, 0x04,
+ /* 00000301 call 0x3ad */ 0xE8, 0xA9, 0x00,
+ /* 00000304 pop si */ 0x5E,
+ /* 00000305 jmp short 0x319 */ 0xEB, 0x12,
+ /* 00000307 push si */ 0x56,
+ /* 00000308 mov si,0x48f */ 0xBE, 0x8F, 0x04,
+ /* 0000030B call 0x3ad */ 0xE8, 0x9F, 0x00,
+ /* 0000030E pop si */ 0x5E,
+ /* 0000030F jmp short 0x319 */ 0xEB, 0x08,
+ /* 00000311 push si */ 0x56,
+ /* 00000312 mov si,0x4a2 */ 0xBE, 0xA2, 0x04,
+ /* 00000315 call 0x3ad */ 0xE8, 0x95, 0x00,
+ /* 00000318 pop si */ 0x5E,
+ /* 00000319 mov [0x4b0],bl */ 0x88, 0x1E, 0xB0, 0x04,
+ /* 0000031D mov [0x4b1],bh */ 0x88, 0x3E, 0xB1, 0x04,
+ /* 00000321 pop ax */ 0x58,
+ /* 00000322 pop dx */ 0x5A,
+ /* 00000323 jmp short 0x395 */ 0xEB, 0x70,
+ /* 00000325 push si */ 0x56,
+ /* 00000326 mov si,0x405 */ 0xBE, 0x05, 0x04,
+ /* 00000329 call 0x3ad */ 0xE8, 0x81, 0x00,
+ /* 0000032C pop si */ 0x5E,
+ /* 0000032D mov bl,[0x4b0] */ 0x8A, 0x1E, 0xB0, 0x04,
+ /* 00000331 mov bh,[0x4b1] */ 0x8A, 0x3E, 0xB1, 0x04,
+ /* 00000335 jmp short 0x395 */ 0xEB, 0x5E,
+ /* 00000337 push si */ 0x56,
+ /* 00000338 mov si,0x43b */ 0xBE, 0x3B, 0x04,
+ /* 0000033B call 0x3ad */ 0xE8, 0x6F, 0x00,
+ /* 0000033E pop si */ 0x5E,
+ /* 0000033F mov bx,0x80 */ 0xBB, 0x80, 0x00,
+ /* 00000342 jmp short 0x395 */ 0xEB, 0x51,
+ /* 00000344 push es */ 0x06,
+ /* 00000345 push di */ 0x57,
+ /* 00000346 push ds */ 0x1E,
+ /* 00000347 push si */ 0x56,
+ /* 00000348 push cx */ 0x51,
+ /* 00000349 push si */ 0x56,
+ /* 0000034A mov si,0x450 */ 0xBE, 0x50, 0x04,
+ /* 0000034D call 0x3ad */ 0xE8, 0x5D, 0x00,
+ /* 00000350 pop si */ 0x5E,
+ /* 00000351 push cs */ 0x0E,
+ /* 00000352 pop ds */ 0x1F,
+ /* 00000353 mov si,0x4b2 */ 0xBE, 0xB2, 0x04,
+ /* 00000356 mov cx,0x80 */ 0xB9, 0x80, 0x00,
+ /* 00000359 cld */ 0xFC,
+ /* 0000035A rep movsb */ 0xF3, 0xA4,
+ /* 0000035C pop cx */ 0x59,
+ /* 0000035D pop si */ 0x5E,
+ /* 0000035E pop ds */ 0x1F,
+ /* 0000035F pop di */ 0x5F,
+ /* 00000360 pop es */ 0x07,
+ /* 00000361 jmp short 0x395 */ 0xEB, 0x32,
+ /* 00000363 push si */ 0x56,
+ /* 00000364 mov si,0x41b */ 0xBE, 0x1B, 0x04,
+ /* 00000367 call 0x3ad */ 0xE8, 0x43, 0x00,
+ /* 0000036A pop si */ 0x5E,
+ /* 0000036B cmp al,0x3 */ 0x3C, 0x03,
+ /* 0000036D jz 0x37e */ 0x74, 0x0F,
+ /* 0000036F cmp al,0x12 */ 0x3C, 0x12,
+ /* 00000371 jz 0x38a */ 0x74, 0x17,
+ /* 00000373 push si */ 0x56,
+ /* 00000374 mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 00000377 call 0x3ad */ 0xE8, 0x33, 0x00,
+ /* 0000037A pop si */ 0x5E,
+ /* 0000037B jmp 0x235 */ 0xE9, 0xB7, 0xFE,
+ /* 0000037E push si */ 0x56,
+ /* 0000037F mov si,0x45c */ 0xBE, 0x5C, 0x04,
+ /* 00000382 call 0x3ad */ 0xE8, 0x28, 0x00,
+ /* 00000385 pop si */ 0x5E,
+ /* 00000386 mov al,0x0 */ 0xB0, 0x00,
+ /* 00000388 jmp short 0x38c */ 0xEB, 0x02,
+ /* 0000038A mov al,0x0 */ 0xB0, 0x00,
+ /* 0000038C push si */ 0x56,
+ /* 0000038D mov si,0x3c2 */ 0xBE, 0xC2, 0x03,
+ /* 00000390 call 0x3ad */ 0xE8, 0x1A, 0x00,
+ /* 00000393 pop si */ 0x5E,
+ /* 00000394 iret */ 0xCF,
+ /* 00000395 push si */ 0x56,
+ /* 00000396 mov si,0x3c2 */ 0xBE, 0xC2, 0x03,
+ /* 00000399 call 0x3ad */ 0xE8, 0x11, 0x00,
+ /* 0000039C pop si */ 0x5E,
+ /* 0000039D mov ax,0x4f */ 0xB8, 0x4F, 0x00,
+ /* 000003A0 iret */ 0xCF,
+ /* 000003A1 push si */ 0x56,
+ /* 000003A2 mov si,0x3c8 */ 0xBE, 0xC8, 0x03,
+ /* 000003A5 call 0x3ad */ 0xE8, 0x05, 0x00,
+ /* 000003A8 pop si */ 0x5E,
+ /* 000003A9 mov ax,0x24f */ 0xB8, 0x4F, 0x02,
+ /* 000003AC iret */ 0xCF,
+ /* 000003AD pusha */ 0x60,
+ /* 000003AE push ds */ 0x1E,
+ /* 000003AF push cs */ 0x0E,
+ /* 000003B0 pop ds */ 0x1F,
+ /* 000003B1 mov dx,0x220 */ 0xBA, 0x20, 0x02,
+ /* 000003B4 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+ /* 000003B7 lodsb */ 0xAC,
+ /* 000003B8 cmp al,0x0 */ 0x3C, 0x00,
+ /* 000003BA jz 0x3bf */ 0x74, 0x03,
+ /* 000003BC out dx,al */ 0xEE,
+ /* 000003BD jmp short 0x3b7 */ 0xEB, 0xF8,
+ /* 000003BF pop ds */ 0x1F,
+ /* 000003C0 popa */ 0x61,
+ /* 000003C1 ret */ 0xC3,
+ /* 000003C2 jna 0x413 */ 0x76, 0x4F,
+ /* 000003C4 imul cx,[di],byte +0xa */ 0x6B, 0x0D, 0x0A,
+ /* 000003C7 add [bp+0x55],dh */ 0x00, 0x76, 0x55,
+ /* 000003CA outsb */ 0x6E,
+ /* 000003CB jnc 0x442 */ 0x73, 0x75,
+ /* 000003CD jo 0x43f */ 0x70, 0x70,
+ /* 000003CF outsw */ 0x6F,
+ /* 000003D0 jc 0x446 */ 0x72, 0x74,
+ /* 000003D2 fs or ax,0xa */ 0x65, 0x64, 0x0D, 0x0A, 0x00,
+ /* 000003D7 jna 0x42e */ 0x76, 0x55,
+ /* 000003D9 outsb */ 0x6E,
+ /* 000003DA imul bp,[bp+0x6f],byte +0x77 */ 0x6B, 0x6E, 0x6F, 0x77,
+ /* 000003DE outsb */ 0x6E,
+ /* 000003DF and [bp+0x75],al */ 0x20, 0x46, 0x75,
+ /* 000003E2 outsb */ 0x6E,
+ /* 000003E3 arpl [si+0x69],si */ 0x63, 0x74, 0x69,
+ /* 000003E6 outsw */ 0x6F,
+ /* 000003E7 outsb */ 0x6E,
+ /* 000003E8 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 000003EB jna 0x434 */ 0x76, 0x47,
+ /* 000003ED gs jz 0x439 */ 0x65, 0x74, 0x49,
+ /* 000003F0 outsb */ 0x6E,
+ /* 000003F1 outsd */ 0x66, 0x6F,
+ /* 000003F3 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 000003F6 jna 0x43f */ 0x76, 0x47,
+ /* 000003F8 gs jz 0x448 */ 0x65, 0x74, 0x4D,
+ /* 000003FB outsw */ 0x6F,
+ /* 000003FC gs dec cx */ 0x64, 0x65, 0x49,
+ /* 000003FF outsb */ 0x6E,
+ /* 00000400 outsd */ 0x66, 0x6F,
+ /* 00000402 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 00000405 jna 0x44e */ 0x76, 0x47,
+ /* 00000407 gs jz 0x457 */ 0x65, 0x74, 0x4D,
+ /* 0000040A outsw */ 0x6F,
+ /* 0000040B gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 00000410 jna 0x465 */ 0x76, 0x53,
+ /* 00000412 gs jz 0x462 */ 0x65, 0x74, 0x4D,
+ /* 00000415 outsw */ 0x6F,
+ /* 00000416 gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 0000041B jna 0x470 */ 0x76, 0x53,
+ /* 0000041D gs jz 0x46d */ 0x65, 0x74, 0x4D,
+ /* 00000420 outsw */ 0x6F,
+ /* 00000421 gs dec sp */ 0x64, 0x65, 0x4C,
+ /* 00000424 gs a32 popa */ 0x65, 0x67, 0x61,
+ /* 00000427 arpl [bx+di+0xd],di */ 0x63, 0x79, 0x0D,
+ /* 0000042A or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000042C jna 0x483 */ 0x76, 0x55,
+ /* 0000042E outsb */ 0x6E,
+ /* 0000042F imul bp,[bx+0x77],byte +0x6e */ 0x6B, 0x6F, 0x77, 0x6E,
+ /* 00000433 and [di+0x6f],cl */ 0x20, 0x4D, 0x6F,
+ /* 00000436 gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 0000043B jna 0x484 */ 0x76, 0x47,
+ /* 0000043D gs jz 0x490 */ 0x65, 0x74, 0x50,
+ /* 00000440 insw */ 0x6D,
+ /* 00000441 inc bx */ 0x43,
+ /* 00000442 popa */ 0x61,
+ /* 00000443 jo 0x4a6 */ 0x70, 0x61,
+ /* 00000445 bound bp,[bx+di+0x6c] */ 0x62, 0x69, 0x6C,
+ /* 00000448 imul si,[si+0x69],word 0x7365 */ 0x69, 0x74, 0x69, 0x65, 0x73,
+ /* 0000044D or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 00000450 jna 0x4a4 */ 0x76, 0x52,
+ /* 00000452 gs popa */ 0x65, 0x61,
+ /* 00000454 fs inc bp */ 0x64, 0x45,
+ /* 00000456 imul sp,[fs:si+0xd],word 0xa */ 0x64, 0x69, 0x64, 0x0D, 0x0A, 0x00,
+ /* 0000045C jna 0x4aa */ 0x76, 0x4C,
+ /* 0000045E gs a32 popa */ 0x65, 0x67, 0x61,
+ /* 00000461 arpl [bx+di+0x4d],di */ 0x63, 0x79, 0x4D,
+ /* 00000464 outsw */ 0x6F,
+ /* 00000465 xor cx,[gs:di] */ 0x64, 0x65, 0x33, 0x0D,
+ /* 00000469 or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000046B insw */ 0x6D,
+ /* 0000046C outsw */ 0x6F,
+ /* 0000046D gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000470 ss xor al,0x30 */ 0x36, 0x34, 0x30,
+ /* 00000473 js 0x4a9 */ 0x78, 0x34,
+ /* 00000475 cmp [bx+si],dh */ 0x38, 0x30,
+ /* 00000477 js 0x4ac */ 0x78, 0x33,
+ /* 00000479 xor cl,[di] */ 0x32, 0x0D,
+ /* 0000047B or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000047D insw */ 0x6D,
+ /* 0000047E outsw */ 0x6F,
+ /* 0000047F gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000482 cmp [bx+si],dh */ 0x38, 0x30,
+ /* 00000484 xor [bx+si+0x36],bh */ 0x30, 0x78, 0x36,
+ /* 00000487 xor [bx+si],dh */ 0x30, 0x30,
+ /* 00000489 js 0x4be */ 0x78, 0x33,
+ /* 0000048B xor cl,[di] */ 0x32, 0x0D,
+ /* 0000048D or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000048F insw */ 0x6D,
+ /* 00000490 outsw */ 0x6F,
+ /* 00000491 gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000494 xor [bx+si],si */ 0x31, 0x30,
+ /* 00000496 xor dh,[si] */ 0x32, 0x34,
+ /* 00000498 js 0x4d1 */ 0x78, 0x37,
+ /* 0000049A cmp [ss:bx+si+0x33],bh */ 0x36, 0x38, 0x78, 0x33,
+ /* 0000049E xor cl,[di] */ 0x32, 0x0D,
+ /* 000004A0 or al,[bx+si] */ 0x0A, 0x00,
+ /* 000004A2 insw */ 0x6D,
+ /* 000004A3 outsw */ 0x6F,
+ /* 000004A4 gs pop di */ 0x64, 0x65, 0x5F,
+ /* 000004A7 jnz 0x517 */ 0x75, 0x6E,
+ /* 000004A9 jnz 0x51e */ 0x75, 0x73,
+ /* 000004AB fs or ax,0xa */ 0x65, 0x64, 0x0D, 0x0A, 0x00,
+ /* 000004B0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004BA add [bx+si],al */ 0x00, 0x00,
+ /* 000004BC add [bx+si],al */ 0x00, 0x00,
+ /* 000004BE add [bx+si],al */ 0x00, 0x00,
+ /* 000004C0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004CA add [bx+si],al */ 0x00, 0x00,
+ /* 000004CC add [bx+si],al */ 0x00, 0x00,
+ /* 000004CE add [bx+si],al */ 0x00, 0x00,
+ /* 000004D0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004DA add [bx+si],al */ 0x00, 0x00,
+ /* 000004DC add [bx+si],al */ 0x00, 0x00,
+ /* 000004DE add [bx+si],al */ 0x00, 0x00,
+ /* 000004E0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004EA add [bx+si],al */ 0x00, 0x00,
+ /* 000004EC add [bx+si],al */ 0x00, 0x00,
+ /* 000004EE add [bx+si],al */ 0x00, 0x00,
+ /* 000004F0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004FA add [bx+si],al */ 0x00, 0x00,
+ /* 000004FC add [bx+si],al */ 0x00, 0x00,
+ /* 000004FE add [bx+si],al */ 0x00, 0x00,
+ /* 00000500 add [bx+si],al */ 0x00, 0x00,
+ /* 00000502 add [bx+si],al */ 0x00, 0x00,
+ /* 00000504 add [bx+si],al */ 0x00, 0x00,
+ /* 00000506 add [bx+si],al */ 0x00, 0x00,
+ /* 00000508 add [bx+si],al */ 0x00, 0x00,
+ /* 0000050A add [bx+si],al */ 0x00, 0x00,
+ /* 0000050C add [bx+si],al */ 0x00, 0x00,
+ /* 0000050E add [bx+si],al */ 0x00, 0x00,
+ /* 00000510 add [bx+si],al */ 0x00, 0x00,
+ /* 00000512 add [bx+si],al */ 0x00, 0x00,
+ /* 00000514 add [bx+si],al */ 0x00, 0x00,
+ /* 00000516 add [bx+si],al */ 0x00, 0x00,
+ /* 00000518 add [bx+si],al */ 0x00, 0x00,
+ /* 0000051A add [bx+si],al */ 0x00, 0x00,
+ /* 0000051C add [bx+si],al */ 0x00, 0x00,
+ /* 0000051E add [bx+si],al */ 0x00, 0x00,
+ /* 00000520 add [bx+si],al */ 0x00, 0x00,
+ /* 00000522 add [bx+si],al */ 0x00, 0x00,
+ /* 00000524 add [bx+si],al */ 0x00, 0x00,
+ /* 00000526 add [bx+si],al */ 0x00, 0x00,
+ /* 00000528 add [bx+si],al */ 0x00, 0x00,
+ /* 0000052A add [bx+si],al */ 0x00, 0x00,
+ /* 0000052C add [bx+si],al */ 0x00, 0x00,
+ /* 0000052E add [bx+si],al */ 0x00, 0x00,
+ /* 00000530 add [bx+si],al */ 0x00, 0x00,
+ /* 00000532 add [bx+si],al */ 0x00, 0x00,
+};
+#endif
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.sh b/OvmfPkg/IntelGvtGopDxe/VbeShim.sh
new file mode 100755
index 000000000000..4f61e5220b01
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+###
+# @file
+# Shell script to assemble and dump the fake Int10h handler from NASM source to
+# a C array.
+#
+# Copyright (C) 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+set -e -u
+
+STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
+
+#
+# Install exit handler -- remove temporary files.
+#
+exit_handler()
+{
+ rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
+ "$STEM".bytes
+}
+trap exit_handler EXIT
+
+#
+# Assemble the source file.
+#
+nasm -o "$STEM".bin "$STEM".asm
+
+#
+# Disassemble it, in order to get a binary dump associated with the source.
+# (ndisasm doesn't recognize the "--" end-of-options delimiter.)
+#
+ndisasm "$STEM".bin >"$STEM".disasm
+
+#
+# Create three files, each with one column of the disassembly.
+#
+# The first column contains the offsets, and it starts the comment.
+#
+cut -c 1-8 -- "$STEM".disasm \
+| sed -e 's,^, /* ,' >"$STEM".offsets
+
+#
+# The second column contains the assembly-language instructions, and it closes
+# the comment. We first pad it to 30 characters.
+#
+cut -c 29- -- "$STEM".disasm \
+| sed -e 's,$, ,' \
+ -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
+
+#
+# The third column contains the bytes corresponding to the instruction,
+# represented as C integer constants. First strip trailing whitespace from the
+# middle column of the input disassembly, then process pairs of nibbles.
+#
+cut -c 11-28 -- "$STEM".disasm \
+| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' | sed 's/0x ,//g' >"$STEM".bytes
+
+#
+# Write the output file, recombining the columns. The output should have CRLF
+# line endings.
+#
+{
+ printf '//\n'
+ printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
+ "$(basename -- "$0")"
+ printf '//\n'
+ printf '#ifndef _VBE_SHIM_H_\n'
+ printf '#define _VBE_SHIM_H_\n'
+ printf 'STATIC CONST UINT8 gVbeShim[] = {\n'
+ paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
+ printf '};\n'
+ printf '#endif\n'
+} \
+| unix2dos >"$STEM".h
diff --git a/OvmfPkg/IntelGvtGopDxe/VirtualGpu.c b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.c
new file mode 100644
index 000000000000..dc2c23706c8b
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.c
@@ -0,0 +1,400 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "VirtualGpu.h"
+#include "GpuReg.h"
+#include "Gtt.h"
+#include "Display.h"
+#include <Library/QemuFwCfgLib.h>
+
+EFI_STATUS
+IntelVirtualGpuActive (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ PCI_TYPE00 PciHdr = {0};
+ UINT64 Magic = 0;
+ UINT32 Version = 0;
+ UINT16 VerMajor = 0, VerMinor = 0;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (PciHdr) / sizeof (UINT32),
+ &PciHdr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read PCI config header, status %d\n", Status
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ if (!IS_PCI_DISPLAY (&PciHdr) || PciHdr.Hdr.VendorId != 0x8086) {
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "Skip non Intel PCI Display [%04x:%04x] class:%x\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, PciHdr.Hdr.ClassCode[2]
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BAR_IDX0,
+ vgtif_reg(magic),
+ 1,
+ &Magic
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read GVT magic from [%04x:%04x], status %d\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, Status
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ if (Magic != VGT_MAGIC) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Read magic from [%04x:%04x], get %x expect %x\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, Magic, VGT_MAGIC
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ vgtif_reg(version_major),
+ 1,
+ &Version
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read GVT version from [%04x:%04x], status %d\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, Status
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ VerMajor = Version & 0xFFFF;
+ VerMinor = (Version & 0xFFFF) >> 16;
+ if (VerMajor < VGT_VERSION_MAJOR) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Check VGT interface version of [%04x:%04x], got %x.%x, expect %x.*\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId,
+ VerMajor, VerMinor, VGT_VERSION_MAJOR
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ GVT_DEBUG (EFI_D_INFO,
+ "Intel GVT-g virtual GPU [%04x:%04x] detected, version %x.%x\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, VerMajor, VerMinor
+ );
+ Status = EFI_SUCCESS;
+
+Done:
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ UINT8 Val8;
+ UINT64 Val64;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ PciIo = Private->PciIo;
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_VENDOR_ID_OFFSET,
+ 1,
+ &VirtualGpu->VendorId
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read PCI_VENDOR_ID_OFFSET, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_DEVICE_ID_OFFSET,
+ 1,
+ &VirtualGpu->DeviceId
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read PCI_DEVICE_ID_OFFSET, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BASE_ADDRESSREG_OFFSET + PCI_BAR_IDX2 * 4,
+ 1,
+ &Val64
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Can't get GMADR from BAR2, status %d\n", Status);
+ goto Done;
+ }
+
+ if (Val64 & 0x1) {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR, "BAR2 isn't memory space, status %d\n", Status);
+ goto Done;
+ }
+
+ switch (Val64 >> 1 & 0x3) {
+ case 0:
+ VirtualGpu->GpuMemAddr = Val64 & 0xFFFFFFF0;
+ GVT_DEBUG (EFI_D_VERBOSE, "BAR2 has 32-bit access space\n");
+ break;
+ case 2:
+ VirtualGpu->GpuMemAddr = Val64 & ~0xF;
+ GVT_DEBUG (EFI_D_VERBOSE, "BAR2 has 64-bit access space\n");
+ break;
+ default:
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR,
+ "BAR2 has unknown access space, status %d\n", Status
+ );
+ goto Done;
+ break;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_REG_MSAC,
+ 1,
+ &Val8
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't get MSAC from %x, status %d\n", PCI_REG_MSAC, Status
+ );
+ goto Done;
+ }
+
+ Val8 &= 0x1F;
+ if (Val8 & 0x10) {
+ VirtualGpu->GpuMemSizeM = 4096;
+ } else {
+ Val8 &= 0xF;
+ if (Val8 & 0x8) {
+ VirtualGpu->GpuMemSizeM = 2048;
+ } else {
+ Val8 &= 0x7;
+ if (Val8 & 0x4) {
+ VirtualGpu->GpuMemSizeM = 1024;
+ } else {
+ Val8 &= 0x3;
+ if (Val8 & 0x2) {
+ VirtualGpu->GpuMemSizeM = 512;
+ } else {
+ if (Val8 & 0x1) {
+ VirtualGpu->GpuMemSizeM = 256;
+ } else {
+ VirtualGpu->GpuMemSizeM = 128;
+ }
+ }
+ }
+ }
+ }
+
+ Status = QemuFwCfgFindFile ("etc/igd-opregion", &FwCfgItem, &FwCfgSize);
(1) This feature still relies on "etc/igd-opregion".

And so, while this driver "poses" as a UEFI_DRIVER module for a PCI
device, it remains a platform driver.

That's still a deal-breaker -- please refer to
<https://bugzilla.tianocore.org/show_bug.cgi?id=935>, specifically
comment 15.

Has there been any improvement regarding the requirement that the
opregion come from QEMU via fw_cfg, for the Windows guest driver's sake?

(I really wish you had first asked about this feature, before authoring
a driver with 4000+ lines!)


(2) If the fw_cfg file in question is not found, the patch simply
ignores it. We log a debug message about it (not even an error message),
but then proceed with the rest of the code as if everything was OK.

Is that intentional?


(3) There's a whole lot of style issues in the code, and I absolutely
don't see myself identifying every single one of those for you, in a
4000+ line driver.

(EFI_D_xxx macro usage, line wrapping issues with multi-line function
calls, comment style problems, an assumption of varargs support with
function-like macros on all edk2 toolchains, building the driver only
for X64, ...)


I'd much prefer if you maintained this driver outside of OvmfPkg
(perhaps somewhere in edk2-platforms, possibly under
Drivers/OptionRomPkg/), and then, given a UEFI driver binary, you passed
it to QEMU via the device's ROM BAR, per
<https://bugzilla.tianocore.org/show_bug.cgi?id=935#c17>.


I'd be *somewhat* open to accepting this driver into OvmfPkg if:

- you formally assume on-going reviewership for the driver
(Maintainers.txt),

- you set the feature test macro in the DSC files to FALSE by default,

- you fix all the style issues with the help of other Intel contributors,

- you explicitly document somewhere that the fw_cfg access is a design
bug in a UEFI driver (especially for an assigned device) -- it remains a
platform driver, contrary to the semblance, for the sake of the arguably
broken Windows guest driver,

- you make the driver 32-bit clean and include it in the IA32 and
IA32X64 DSC files too.


I won't even mention how unreviewable a "patch bomb" like this is; such
a driver should be constructed (erected) gradually over 10-20 patches at
the minimum, isolating the UEFI driver model code from the device
initialization from the various GOP member functions. I won't mention
that because I don't intend to review this driver in depth anyway.

I might be willing to accept it as an optional (disabled by default)
"code dump", as long as you ensure the bare minimum of edk2 style and
build requirements, and take full responsibility for the driver in the
future.

... Honestly, the fact that you never asked about this feature on any
edk2 list, and that you (apparently) never searched the TianoCore
bugzilla tracker for potentially related BZs (such as #935), doesn't
really boost my confidence in this feature.

Laszlo

+ if (Status == EFI_SUCCESS && FwCfgSize == OPREGION_SIZE) {
+ // OpRegion must sit below 4 GB
+ VirtualGpu->OpRegion = SIZE_4GB - 1;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE),
+ &VirtualGpu->OpRegion
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to allocate %d pages size %lx for OpRegion, status %d\n",
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE), OPREGION_SIZE, Status
+ );
+ goto Done;
+ }
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (FwCfgSize, (VOID*)VirtualGpu->OpRegion);
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_REG_ASLS,
+ 1,
+ (UINT32*)&VirtualGpu->OpRegion
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to write OpRegion %p to PCI config offset 0x%x, status %d\n",
+ VirtualGpu->OpRegion, PCI_REG_ASLS, Status
+ );
+ goto Done;
+ } else {
+ GVT_DEBUG (EFI_D_INFO,
+ "OpRegion %p is set to PCI config offset 0x%x\n",
+ VirtualGpu->OpRegion, PCI_REG_ASLS
+ );
+ }
+ } else {
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "Not igd-opregion found in QEMU firmware config\n"
+ );
+ }
+
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.mappable_gmadr.base), &VirtualGpu->VisibleOffset);
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.mappable_gmadr.size), &VirtualGpu->VisibleSize);
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.nonmappable_gmadr.base), &VirtualGpu->InvisibleOffset);
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.nonmappable_gmadr.size), &VirtualGpu->InvisibleSize);
+ VirtualGpu->VisibleGGTTOffset = VirtualGpu->VisibleOffset >> GTT_PAGE_SHIFT;
+ VirtualGpu->VisibleGGTTSize = VirtualGpu->VisibleSize >> GTT_PAGE_SHIFT;
+ VirtualGpu->InvisibleGGTTOffset = VirtualGpu->InvisibleOffset >> GTT_PAGE_SHIFT;
+ VirtualGpu->InvisibleGGTTSize = VirtualGpu->InvisibleSize >> GTT_PAGE_SHIFT;
+
+ GVT_DEBUG (
+ EFI_D_INFO,
+ "GMADR [0x%lx - 0x%lx], size %d MB\n",
+ VirtualGpu->GpuMemAddr,
+ VirtualGpu->GpuMemAddr + VirtualGpu->GpuMemSizeM * 0x100000,
+ VirtualGpu->GpuMemSizeM
+ );
+ GVT_DEBUG (
+ EFI_D_INFO,
+ "visible offset [0x%x - 0x%x] size %d KB, GGTT range [%x - %x]\n",
+ VirtualGpu->VisibleOffset,
+ VirtualGpu->VisibleOffset + VirtualGpu->VisibleSize,
+ VirtualGpu->VisibleSize / 0x400,
+ VirtualGpu->VisibleGGTTOffset,
+ VirtualGpu->VisibleGGTTOffset + VirtualGpu->VisibleGGTTSize
+ );
+ GVT_DEBUG (
+ EFI_D_INFO,
+ "invisible offset [0x%x - 0x%x] size %d KB, GGTT range [%x - %x]\n",
+ VirtualGpu->InvisibleOffset,
+ VirtualGpu->InvisibleOffset + VirtualGpu->InvisibleSize,
+ VirtualGpu->InvisibleSize / 0x400,
+ VirtualGpu->InvisibleGGTTOffset,
+ VirtualGpu->InvisibleGGTTOffset + VirtualGpu->InvisibleGGTTSize
+ );
+
+ Status = IntelVirtualGpuDisplayInit (Private);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to initialize display, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = IntelVirtualGpuSetMode (&Private->GraphicsOutputProtocol, 0);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to set init display mode, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = IntelVirtualGpuNotifyDisplayReady (Private, TRUE);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to notify display ready, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ // Flush all reg after DisplayReady
+ Status = IntelVirtualGpuEnableDisplay (
+ Private,
+ 0,
+ TRUE
+ );
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = IntelVirtualGpuDisplayClean (Private);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Fail to clean display, status %d\n", Status);
+ goto Done;
+ }
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ if (VirtualGpu->OpRegion) {
+ Status = gBS->FreePages (
+ VirtualGpu->OpRegion,
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE)
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePages failed for OpRegion, pages %d, size %d, status %d\n",
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE), OPREGION_SIZE, Status
+ );
+ goto Done;
+ }
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/VirtualGpu.h b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.h
new file mode 100644
index 000000000000..60d80eadb3ac
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.h
@@ -0,0 +1,52 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __VIRTUALGPU_H_
+#define __VIRTUALGPU_H_
+
+#include <Display.h>
+
+#define PCI_REG_MSAC 0x62
+#define PCI_REG_ASLS 0xFC
+
+#define OPREGION_SIZE SIZE_8KB
+
+typedef struct _INTEL_VIRTUAL_GPU {
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ EFI_PHYSICAL_ADDRESS OpRegion;
+ EFI_PHYSICAL_ADDRESS GpuMemAddr;
+ UINT32 GpuMemSizeM;
+ UINT32 VisibleOffset;
+ UINT32 VisibleSize;
+ UINT32 VisibleGGTTOffset;
+ UINT32 VisibleGGTTSize;
+ UINT32 InvisibleOffset;
+ UINT32 InvisibleSize;
+ UINT32 InvisibleGGTTOffset;
+ UINT32 InvisibleGGTTSize;
+ INTEL_VIRTUAL_GPU_DISPLAY Display;
+} INTEL_VIRTUAL_GPU, *PINTEL_VIRTUAL_GPU;
+
+EFI_STATUS
+IntelVirtualGpuActive (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ );
+
+EFI_STATUS
+IntelVirtualGpuInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+IntelVirtualGpuClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+#endif //__VIRTUALGPU_H_


Colin Xu
 

--
Best Regards,
Colin Xu

On Fri, 5 Mar 2021, Laszlo Ersek wrote:
Thanks a lot for your comment, Laszlo! See my reply also end of the patch.
Hi Gerd, Alex, would you mind share your thoughts as well?

Adding Gerd and Alex; some comments below (near the end of the patch --
keeping full context for Gerd's and Alex's sake):

On 03/05/21 07:20, Colin Xu wrote:
Intel GVT-g GOP DXE supports OVMF GOP output its frame buffer to vGPU
partitioned aperture mapped by GGTT, so that the GOP output can be
mediated to its backend for display (i.e. QEMU GTK display via dma-buf).

Unlike ACRN GVT-d integrating native GOP/VBT into it's OVMF, the GVT-g
GOP is an open-source implementation which follows Intel GVT-g framework
to interact with KVMGT in host kernel so that the GOP frame buffer
content can be processed properly.

With GVT-g GOP enabled OVMF, guest VM can output its framebuffer
content to KVMGT via GOP, with a proper backend support (i.e. QEMU GTK
display with dma-buf), the following content is now directly visible to
user unlike previosly need a second GPU:
- OVMF EFI Shell
- Bootloader (i.e. grub)
- OS installation progress. (before built-in GFX driver loaded)
- Pre GFX Driver display (i.e. Android/Linux boot splash or logo,
Windows 8.1 boot progress/safe mode/recovery mode/BSOD/GPU-disabled
desktop, etc.)

GVT-g GOP has below capabilites:
- Check GVT-g compatibility via PV info, only enable GVT-g GOP when it's
compatible with KVMGT.
- R/W MMIO from BAR0.
- R/W Global GTT from BAR0.
- Reserve and program OpRegion address at ASLS location so that guest
driver can decode GVT-g simluated VBT and enabled display properly.
- Reserve guest memory and map to BAR2 partitioned range with proper
GGTT, so that KVMGT can access via proper guest GTT to host GGTT map.
- All supported EFI_GRAPHICS_OUTPUT_BLT_OPERATION from/to video memory.
- Enable/disable GOP content on PIPE_A, PLANE_PRIMARY with proper scaling.
- VBE Shim so that some OS can query non-empty mode info via INT10 call
to enable the desktop when GPU is disabled.

V2:
Program PIPESRC to match active H/V.

Signed-off-by: Colin Xu <colin.xu@intel.com>
---
OvmfPkg/IntelGvtGopDxe/Common.h | 45 +
OvmfPkg/IntelGvtGopDxe/DebugHelper.h | 20 +
OvmfPkg/IntelGvtGopDxe/Display.c | 1077 +++++++++++++++++++++
OvmfPkg/IntelGvtGopDxe/Display.h | 141 +++
OvmfPkg/IntelGvtGopDxe/GopDriver.c | 478 +++++++++
OvmfPkg/IntelGvtGopDxe/GpuReg.c | 91 ++
OvmfPkg/IntelGvtGopDxe/GpuReg.h | 175 ++++
OvmfPkg/IntelGvtGopDxe/Gtt.c | 162 ++++
OvmfPkg/IntelGvtGopDxe/Gtt.h | 51 +
OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf | 59 ++
OvmfPkg/IntelGvtGopDxe/VbeShim.asm | 343 +++++++
OvmfPkg/IntelGvtGopDxe/VbeShim.c | 258 +++++
OvmfPkg/IntelGvtGopDxe/VbeShim.h | 912 +++++++++++++++++
OvmfPkg/IntelGvtGopDxe/VbeShim.sh | 81 ++
OvmfPkg/IntelGvtGopDxe/VirtualGpu.c | 400 ++++++++
OvmfPkg/IntelGvtGopDxe/VirtualGpu.h | 52 +
16 files changed, 4345 insertions(+)
create mode 100644 OvmfPkg/IntelGvtGopDxe/Common.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/DebugHelper.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/Display.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/Display.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/GopDriver.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/GpuReg.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/GpuReg.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/Gtt.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/Gtt.h
create mode 100644 OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf
create mode 100644 OvmfPkg/IntelGvtGopDxe/VbeShim.asm
create mode 100644 OvmfPkg/IntelGvtGopDxe/VbeShim.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/VbeShim.h
create mode 100755 OvmfPkg/IntelGvtGopDxe/VbeShim.sh
create mode 100644 OvmfPkg/IntelGvtGopDxe/VirtualGpu.c
create mode 100644 OvmfPkg/IntelGvtGopDxe/VirtualGpu.h

diff --git a/OvmfPkg/IntelGvtGopDxe/Common.h b/OvmfPkg/IntelGvtGopDxe/Common.h
new file mode 100644
index 000000000000..cf30752eb8f3
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Common.h
@@ -0,0 +1,45 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __COMMON_H_
+
+#include <Protocol/PciIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/GraphicsOutput.h>
+
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include "DebugHelper.h"
+
+#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
+
+typedef struct {
+ UINT64 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 OriginalPciAttr;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutputProtocol;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevPath;
+ VOID *VirtualGpu;
+} GVT_GOP_PRIVATE_DATA;
+
+#define GVT_GOP_MAGIC SIGNATURE_64('G','V','T','G','V','G','O','P')
+#define GVT_GOP_PRIVATE_DATA_FROM_THIS(a) CR(a, GVT_GOP_PRIVATE_DATA, GraphicsOutputProtocol, GVT_GOP_MAGIC)
+
+#define __COMMON_H_
+#endif //__COMMON_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/DebugHelper.h b/OvmfPkg/IntelGvtGopDxe/DebugHelper.h
new file mode 100644
index 000000000000..75158d713ec3
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/DebugHelper.h
@@ -0,0 +1,20 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __DEBUGHELPER_H_
+#define __DEBUGHELPER_H_
+
+#include <Library/DebugLib.h>
+
+#define GVT_DEBUG(ErrLevel, Fmt, Args...) \
+ do { \
+ DEBUG ((ErrLevel, "GvtGop: "Fmt, ##Args));\
+ } while (FALSE)
+
+#endif //__DEBUGHELPER_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/Display.c b/OvmfPkg/IntelGvtGopDxe/Display.c
new file mode 100644
index 000000000000..133de25ff03c
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Display.c
@@ -0,0 +1,1077 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "Display.h"
+#include "GpuReg.h"
+#include "Gtt.h"
+#include "VirtualGpu.h"
+
+EFI_STATUS
+IntelVirtualGpuDisplayInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+ UINT32 Val32;
+ UINTN Width, Height, ModeNumber;
+ EFI_TPL OriginalTPL;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ /*
+ * If PcdVideoHorizontalResolution or PcdVideoVerticalResolution is not set,
+ * GOP will query the mode list reported to find the highest resolution.
+ * Otherwise, check if the set PcdVideo*Resolution is defined.
+ * If not supported, try 800x600 which is required by UEFI/EFI spec.
+ * If still not supported, use the 1st mode in mode list.
+ * If there are multiple video devices, graphic console driver will set all
+ * the video devices to the same mode.
+ * According to UEFI/EFI spec, in addition to platform design guide, on-board
+ * graphics should support native mode of the display, plug-in graphics
+ * should support 800x600x32 or 640x480x32.
+ * According to some OS requirement (i.e. UEFI requirment for Windows 10),
+ * integrated displays should support panel native resolution and external
+ * displays should support the maximum resolution of both GPU and display in
+ * GOP. For alternate display output, it should support native or highest
+ * compatible resolution, otherwise support an known mode to be compatible
+ * with as many monitors as possible (640x480, 1024x768).
+ * Due to above requirement, use native resolution if PcdVideo*Resolution is
+ * not defined. To reduce GGTT write overhead, also limit the maximum to
+ * DISPLAY_WIDTH_MAX/DISPLAY_HEIGHT_MAX.
+ */
+
+ RegRead32 (Private, HTOTAL(PIPE_A), &Val32);
+ Display->HActive = (Val32 & 0xFFF) + 1;
+ RegRead32 (Private, VTOTAL(PIPE_A), &Val32);
+ Display->VActive = (Val32 & 0xFFF) + 1;
+
+ if (Display->HActive != 0 && Display->VActive != 0) {
+ Width = Display->HActive;
+ Height = Display->VActive;
+ if (Display->HActive > DISPLAY_WIDTH_MAX ||
+ Display->VActive > DISPLAY_HEIGHT_MAX) {
+ Width = DISPLAY_WIDTH_MAX;
+ Height = DISPLAY_HEIGHT_MAX;
+ }
+ } else {
+ Width = DISPLAY_WIDTH_DEFAULT;
+ Height = DISPLAY_HEIGHT_DEFAULT;
+ }
+
+ Display->Width = Width;
+ Display->Height = Height;
+ Display->Format = PixelBlueGreenRedReserved8BitPerColor;
+ Display->Bpp = 4;
+ Display->MaxMode = 1;
+
+ // Add default if defined
+ if (PcdGet32 (PcdVideoHorizontalResolution) != 0 &&
+ PcdGet32 (PcdVideoVerticalResolution) != 0 &&
+ PcdGet32 (PcdVideoHorizontalResolution) != Width &&
+ PcdGet32 (PcdVideoVerticalResolution) != Height) {
+ ++Display->MaxMode;
+ }
+
+ Display->CurrentMode = DISPLAY_MODE_INVALID;
+ Display->FrameBufferBltConfigure = NULL;
+ Display->FrameBufferBltConfigureSize = 0;
+
+ // Linear must start at 256K, stride align at 64
+ Display->WidthBytes = Display->Width * Display->Bpp;
+ Display->StrideBytes = ALIGN_VALUE (Display->WidthBytes, 64);
+ Display->FbSize = Display->StrideBytes * Display->Height;
+ Display->Pages = EFI_SIZE_TO_PAGES (Display->FbSize);
+
+ Display->FbGMAddr = VirtualGpu->GpuMemAddr + VirtualGpu->VisibleOffset;
+ Display->FbGMAddr = ALIGN_VALUE (Display->FbGMAddr, SIZE_256KB);
+
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiReservedMemoryType,
+ Display->Pages,
+ &Display->FbPhysicalAddr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePages failed for display FB, pages %d, size %lx, status %d\n",
+ Display->Pages, Display->FbSize, Status
+ );
+ return Status;
+ }
+
+ Status = UpdateGGTT (Private,
+ Display->FbGMAddr,
+ Display->FbPhysicalAddr,
+ Display->Pages
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to Update GGTT for display, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+ Status = IntelVirtualGpuBltVideoFill (
+ Display,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}},
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height});
+ gBS->RestoreTPL (OriginalTPL);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to clear rectangle at [%d, %d] size %dx%d with color 0x%08x, status %d\n",
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.X,
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.Y,
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.Width,
+ (BLT_RECTANGLE){0, 0, Display->Width, Display->Height}.Height,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}}.Raw,
+ Status
+ );
+ goto Done;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode,
+ (VOID **)&Display->ModeList
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for display mode list, size %d, status %d\n",
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode,
+ Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ for (ModeNumber = 0; ModeNumber < Display->MaxMode; ModeNumber++) {
+ Display->ModeList[ModeNumber].Version = 0;
+ Display->ModeList[ModeNumber].HorizontalResolution = Display->Width;
+ Display->ModeList[ModeNumber].VerticalResolution = Display->Height;
+ Display->ModeList[ModeNumber].PixelFormat = Display->Format;
+ Display->ModeList[ModeNumber].PixelsPerScanLine = Display->Width;
+ }
+ if (Display->MaxMode > 1) {
+ Display->ModeList[1].HorizontalResolution = PcdGet32 (PcdVideoHorizontalResolution);
+ Display->ModeList[1].VerticalResolution = PcdGet32 (PcdVideoVerticalResolution);
+ Display->ModeList[1].PixelsPerScanLine = PcdGet32 (PcdVideoHorizontalResolution);
+ }
+
+ Private->GraphicsOutputProtocol.QueryMode = IntelVirtualGpuQueryMode;
+ Private->GraphicsOutputProtocol.SetMode = IntelVirtualGpuSetMode;
+ Private->GraphicsOutputProtocol.Blt = IntelVirtualGpuBlt;
+ Private->GraphicsOutputProtocol.Mode->MaxMode = Display->MaxMode;
+ Private->GraphicsOutputProtocol.Mode->Mode = Display->CurrentMode;
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo =
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode;
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo,
+ (VOID **)&Private->GraphicsOutputProtocol.Mode->Info
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for display mode info, size %d, status %d\n",
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo, Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ CopyMem (
+ Private->GraphicsOutputProtocol.Mode->Info,
+ Display->ModeList,
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION) * Display->MaxMode
+ );
+
+ Private->GraphicsOutputProtocol.Mode->FrameBufferBase = Display->FbGMAddr;
+ Private->GraphicsOutputProtocol.Mode->FrameBufferSize = Display->FbSize;
+
+ InstallVbeShim (L"GVT-g VBIOS", Display->FbGMAddr);
+
+ GVT_DEBUG (EFI_D_INFO,
+ "modes %d, max %dx%d, OVMF default %dx%d\n",
+ Display->MaxMode,
+ Display->Width, Display->Height,
+ PcdGet32 (PcdVideoHorizontalResolution),
+ PcdGet32 (PcdVideoVerticalResolution)
+ );
+ for (ModeNumber = 0; ModeNumber < Display->MaxMode; ModeNumber++) {
+ GVT_DEBUG (EFI_D_INFO,
+ " mode %d: %dx%d BGRX, stride %d\n",
+ ModeNumber,
+ Display->ModeList[ModeNumber].HorizontalResolution,
+ Display->ModeList[ModeNumber].VerticalResolution,
+ ALIGN_VALUE (Display->ModeList[ModeNumber].HorizontalResolution * Display->Bpp, 64)
+ );
+ }
+ GVT_DEBUG (EFI_D_INFO,
+ "FrameBuffer: GMADR %lx, PADDR %lx, size %lx, pages %d, INTERNAL_BLT %d\n",
+ Display->FbGMAddr, Display->FbPhysicalAddr, Display->FbSize, Display->Pages,
+ DISPLAY_USE_INTERNAL_BLT
+ );
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+
+}
+
+EFI_STATUS
+IntelVirtualGpuDisplayClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (Private->GraphicsOutputProtocol.Mode->Info) {
+ Status = gBS->FreePool (Private->GraphicsOutputProtocol.Mode->Info);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePool failed for display mode info, size %d, status %d\n",
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo, Status
+ );
+ goto Done;
+ }
+ Private->GraphicsOutputProtocol.Mode->SizeOfInfo = 0;
+ Private->GraphicsOutputProtocol.Mode->Info = NULL;
+ }
+ Private->GraphicsOutputProtocol.Mode->MaxMode = 0;
+ Private->GraphicsOutputProtocol.Mode->Mode = DISPLAY_MODE_INVALID;
+
+ if (Display->FbPhysicalAddr) {
+ Status = gBS->FreePages (Display->FbPhysicalAddr, Display->Pages);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePages failed for display FB, pages %d, size %lx, status %d\n",
+ Display->Pages, Display->FbSize, Status
+ );
+ goto Done;
+ }
+ Display->FbPhysicalAddr = 0;
+ Display->Pages = 0;
+ Display->FbSize = 0;
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (This);
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)GvtGopPrivate->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (ModeNumber >= Display->MaxMode) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Invalid ModeNumber, request %d, max %d, status %d\n",
+ ModeNumber, Display->MaxMode, Status
+ );
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ (VOID **)Info
+ );
+ if (EFI_ERROR (Status) || *Info == NULL) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for queried mode info, size %d, status %d\n",
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+ CopyMem (
+ *Info,
+ &Display->ModeList[ModeNumber],
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
+ );
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (This);
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)GvtGopPrivate->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (ModeNumber >= Display->MaxMode) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Invalid ModeNumber, request %d, max %d, status %d\n",
+ ModeNumber, Display->MaxMode, Status
+ );
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+#if (DISPLAY_USE_INTERNAL_BLT == 1)
+ Status = IntelVirtualGpuBltVideoFill (
+ Display,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}},
+ (BLT_RECTANGLE){0, 0, This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution});
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "IntelVirtualGpuBltVideoFill failed for mode %d, status %d\n",
+ ModeNumber,
+ Status
+ );
+ }
+#else
+ Status = FrameBufferBltConfigure (
+ (VOID*) (UINTN) This->Mode->FrameBufferBase,
+ This->Mode->Info,
+ Display->FrameBufferBltConfigure,
+ &Display->FrameBufferBltConfigureSize
+ );
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ if (Display->FrameBufferBltConfigure != NULL) {
+ Status = gBS->FreePool (Display->FrameBufferBltConfigure);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePool failed for FrameBufferBltConfigure, status %d\n",
+ Status
+ );
+ goto Done;
+ }
+ }
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ Display->FrameBufferBltConfigureSize,
+ (VOID **)&Display->FrameBufferBltConfigure
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for FrameBufferBltConfigure, size %d, status %d\n",
+ Display->FrameBufferBltConfigureSize,
+ Status
+ );
+ goto Done;
+ }
+
+ Status = FrameBufferBltConfigure (
+ (VOID*) (UINTN) This->Mode->FrameBufferBase,
+ This->Mode->Info,
+ Display->FrameBufferBltConfigure,
+ &Display->FrameBufferBltConfigureSize
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FrameBufferBltConfigure failed for mode %d, status %d\n",
+ ModeNumber,
+ Status
+ );
+ goto Done;
+ }
+ }
+
+ Status = FrameBufferBlt (
+ Display->FrameBufferBltConfigure,
+ &(EFI_GRAPHICS_OUTPUT_BLT_PIXEL){0, 0, 0, 0},
+ EfiBltVideoFill,
+ 0, 0,
+ 0, 0,
+ This->Mode->Info->HorizontalResolution,
+ This->Mode->Info->VerticalResolution,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FrameBufferBlt BltOperation %d failed for mode %d, color 0x%08x, status %d\n",
+ EfiBltVideoFill,
+ ModeNumber,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION){{0, 0, 0, 0}}.Raw,
+ Status
+ );
+ }
+#endif
+
+ Status = IntelVirtualGpuEnableDisplay (
+ GvtGopPrivate,
+ ModeNumber,
+ FALSE
+ );
+
+ Status = IntelVirtualGpuEnableDisplay (
+ GvtGopPrivate,
+ ModeNumber,
+ TRUE
+ );
+
+ // Set current mode info in GOP
+ This->Mode->Mode = ModeNumber;
+ CopyMem (
+ This->Mode->Info,
+ &Display->ModeList[ModeNumber],
+ sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
+ );
+
+ GVT_DEBUG (EFI_D_INFO, "Set mode %d, %dx%d, status %d\n",
+ ModeNumber,
+ Display->ModeList[ModeNumber].HorizontalResolution,
+ Display->ModeList[ModeNumber].VerticalResolution,
+ Status
+ );
+
+Done:
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+ EFI_TPL OriginalTPL;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (This);
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)GvtGopPrivate->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+#if (DISPLAY_USE_INTERNAL_BLT == 1)
+ switch (BltOperation) {
+ case EfiBltVideoFill:
+ Status = IntelVirtualGpuBltVideoFill (
+ Display,
+ (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION)(*BltBuffer),
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height});
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ break;
+ case EfiBltVideoToBltBuffer:
+ Status = IntelVirtualGpuBltVideoToBuffer (
+ Display,
+ BltBuffer,
+ (BLT_RECTANGLE){SourceX, SourceY, Width, Height},
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height},
+ Delta
+ );
+ break;
+ case EfiBltBufferToVideo:
+ Status = IntelVirtualGpuBltVideoFromBuffer (
+ Display,
+ BltBuffer,
+ (BLT_RECTANGLE){SourceX, SourceY, Width, Height},
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height},
+ Delta
+ );
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ break;
+ case EfiBltVideoToVideo:
+ Status = IntelVirtualGpuBltVideoToVideo (
+ Display,
+ (BLT_RECTANGLE){SourceX, SourceY, Width, Height},
+ (BLT_RECTANGLE){DestinationX, DestinationY, Width, Height}
+ );
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ break;
+ default:
+ GVT_DEBUG (EFI_D_INFO, "Unsupported EFI_GRAPHICS_OUTPUT_BLT_OPERATION %d\n", BltOperation);
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+#else
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+ case EfiBltVideoFill:
+ case EfiBltBufferToVideo:
+ case EfiBltVideoToVideo:
+ Status = FrameBufferBlt (
+ Display->FrameBufferBltConfigure,
+ BltBuffer,
+ BltOperation,
+ SourceX,
+ SourceY,
+ DestinationX,
+ DestinationY,
+ Width,
+ Height,
+ Delta
+ );
+ if (BltOperation != EfiBltVideoToBltBuffer) {
+ RegWrite32 (GvtGopPrivate,
+ PLANE_SURF(PIPE_A, PLANE_PRIMARY),
+ Display->FbGMAddr
+ );
+ }
+ break;
+ default:
+ GVT_DEBUG (EFI_D_INFO, "Unsupported EFI_GRAPHICS_OUTPUT_BLT_OPERATION %d\n", BltOperation);
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+#endif
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuEnableDisplay (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 ModeNumber,
+ IN BOOLEAN Enable
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ PINTEL_VIRTUAL_GPU_DISPLAY Display;
+ UINT32 Width, Height, Val32;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Display = &VirtualGpu->Display;
+
+ if (ModeNumber >= Display->MaxMode) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Invalid ModeNumber, request %d, max %d, status %d\n",
+ ModeNumber, Display->MaxMode, Status
+ );
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Width = Display->ModeList[ModeNumber].HorizontalResolution;
+ Height = Display->ModeList[ModeNumber].VerticalResolution;
+
+ if (Enable) {
+ Display->CurrentMode = ModeNumber;
+
+ Val32 = (Display->HActive - 1) << 16;
+ Val32 |= Display->VActive;
+ RegWrite32 (Private, PIPESRC(PIPE_A), Val32);
+
+ RegRead32 (Private, PIPE_CONF(PIPE_A), &Val32);
+ Val32 |= PIPE_CONF_ENABLE;
+ RegWrite32 (Private, PIPE_CONF(PIPE_A), Val32);
+
+ Val32 = (Width - 1) & 0xFFF;
+ Val32 |= ((Height - 1) & 0xFFF) << 16;
+ RegWrite32 (Private, PLANE_SIZE(PIPE_A, PLANE_PRIMARY), Val32);
+ RegWrite32 (Private, PLANE_POS(PIPE_A, PLANE_PRIMARY), 0);
+
+ // Convert mode with to stride in chunks of 64 bytes as required by PLANE_STRIDE
+ Val32 = Display->ModeList[ModeNumber].HorizontalResolution * Display->Bpp;
+ Val32 = ALIGN_VALUE (Val32, 64);
+ Val32 = (Val32 / 64) & PLANE_STRIDE_MASK;
+ RegWrite32 (Private, PLANE_STRIDE(PIPE_A, PLANE_PRIMARY), Val32);
+
+ RegWrite32 (Private, PLANE_SURF(PIPE_A, PLANE_PRIMARY), Display->FbGMAddr);
+
+ // Stretch to fullscreen if current mode is smaller than H/V active.
+ if (Display->HActive != Width ||
+ Display->VActive != Height) {
+ RegWrite32 (Private, PS_WIN_POS(PIPE_A, 0), 0);
+ RegWrite32 (Private,
+ PS_WIN_SZ(PIPE_A, 0),
+ Display->HActive << 16 | Display->VActive
+ );
+ RegRead32 (Private, PS_CTRL(PIPE_A, 0), &Val32);
+ Val32 |= PS_CTRL_SCALER_EN;
+ Val32 &= ~PS_CTRL_SCALER_MODE_MASK;
+ Val32 |= PS_CTRL_SCALER_MODE_DYN;
+ Val32 &= ~PS_CTRL_SCALER_BINDING_MASK;
+ Val32 |= PS_CTRL_PLANE_SEL(PLANE_PRIMARY);
+ Val32 &= ~PS_CTRL_SCALER_FILTER_MASK;
+ Val32 |= PS_CTRL_SCALER_FILTER_MEDIUM;
+ RegWrite32 (Private, PS_CTRL(PIPE_A, 0), Val32);
+ }
+
+ RegRead32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), &Val32);
+ Val32 |= PLANE_CTL_ENABLE;
+ Val32 &= ~PLANE_CTL_PIPE_GAMMA_ENABLE;
+ Val32 &= ~PLANE_CTL_FORMAT_MASK;
+ Val32 |= PLANE_CTL_FORMAT_XRGB_8888;
+ Val32 &= ~PLANE_CTL_PIPE_CSC_ENABLE;
+ Val32 &= ~PLANE_CTL_KEY_ENABLE_MASK;
+ Val32 &= ~PLANE_CTL_ORDER_RGBX;
+ if (Display->ModeList[ModeNumber].PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
+ Val32 |= PLANE_CTL_ORDER_RGBX;
+ }
+ Val32 &= ~PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
+ Val32 |= PLANE_CTL_PLANE_GAMMA_DISABLE;
+ Val32 &= ~PLANE_CTL_TILED_MASK;
+ Val32 |= PLANE_CTL_TILED_LINEAR;
+ Val32 &= ~PLANE_CTL_ASYNC_FLIP;
+ Val32 &= ~PLANE_CTL_ALPHA_MASK;
+ Val32 |= PLANE_CTL_ALPHA_DISABLE;
+ Val32 &= ~PLANE_CTL_ROTATE_MASK;
+ Val32 |= PLANE_CTL_ROTATE_0;
+ RegWrite32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), Val32);
+ } else {
+ Display->CurrentMode = DISPLAY_MODE_INVALID;
+
+ RegRead32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), &Val32);
+ Val32 &= ~PLANE_CTL_ENABLE;
+ RegWrite32 (Private, PLANE_CTL(PIPE_A, PLANE_PRIMARY), Val32);
+ RegWrite32 (Private, PLANE_SURF(PIPE_A, PLANE_PRIMARY), 0);
+
+ RegRead32 (Private, PS_CTRL(PIPE_A, 0), &Val32);
+ Val32 &= ~PS_CTRL_SCALER_EN;
+ RegWrite32 (Private, PS_CTRL(PIPE_A, 0), Val32);
+ RegWrite32 (Private, PS_WIN_POS(PIPE_A, 0), 0);
+ RegWrite32 (Private, PS_WIN_SZ(PIPE_A, 0), 0);
+
+ RegRead32 (Private, PIPE_CONF(PIPE_A), &Val32);
+ Val32 &= ~PIPE_CONF_ENABLE;
+ RegWrite32 (Private, PIPE_CONF(PIPE_A), Val32);
+ }
+
+ Status = EFI_SUCCESS;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: %a mode %dx%d 0x%x, scaling %a\n",
+ __FUNCTION__,
+ Enable ? "Enable" : "Disable",
+ Width,
+ Height,
+ Display->FbGMAddr,
+ (Display->HActive != Width ||
+ Display->VActive != Height) ? "On" : "Off");
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuNotifyDisplayReady (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN BOOLEAN Ready
+ )
+{
+ return RegWrite32 (
+ Private,
+ vgtif_reg(display_ready),
+ Ready ? VGT_DRV_DISPLAY_READY : VGT_DRV_DISPLAY_NOT_READY
+ );
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFill (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltPixel,
+ IN BLT_RECTANGLE Destination
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *DestAddr;
+ UINTN DestBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Destination.Width == 0 || Destination.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoFill invalid destination rectangle [%d, %d] \n",
+ Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Destination.X + Destination.Width > Display->Width) ||
+ (Destination.Y + Destination.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoFill destination [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Destination.X, Destination.Y,
+ Destination.X + Destination.Width, Destination.Y + Destination.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ if (Destination.Width * Display->Bpp == ModeStrideBytes) {
+ DestAddr = (UINT8*)Display->FbGMAddr + Destination.Y * ModeStrideBytes;
+ DestBytes = Destination.Width * Display->Bpp * Destination.Height;
+ SetMem32 ((VOID*)DestAddr, DestBytes, BltPixel.Raw);
+ } else {
+
+ for (Line = 0; Line < Destination.Height; Line++) {
+ DestAddr = (UINT8*)Display->FbGMAddr +
+ (Line + Destination.Y) * ModeStrideBytes +
+ Destination.X * Display->Bpp;
+ DestBytes = Destination.Width * Display->Bpp;
+
+ SetMem32 (DestAddr, DestBytes, BltPixel.Raw);
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *SourceAddr, *DestAddr;
+ UINTN DestStride, CopyBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Source.Width == 0 || Source.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToBltBuffer invalid source rectangle [%d, %d] \n",
+ Source.Width, Source.Height
+ );
+ goto Done;
+ }
+
+ if (Source.Width != Destination.Width ||
+ Source.Height != Destination.Height) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToBltBuffer size mismatch: source %dx%d, destination %dx%d\n",
+ Source.Width, Source.Height, Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Source.X + Source.Width > Display->Width) ||
+ (Source.Y + Source.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToBltBuffer source [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Source.X, Source.Y,
+ Source.X + Source.Width, Source.Y + Source.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Destination.X != 0 || Destination.Y != 0) {
+ DestStride = Delta;
+ } else {
+ DestStride = Destination.Width * Display->Bpp;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ for (Line = 0; Line < Source.Height; Line++) {
+ SourceAddr = (UINT8*)Display->FbGMAddr +
+ (Source.Y + Line) * ModeStrideBytes +
+ Source.X * Display->Bpp;
+ DestAddr = (UINT8*)BltBuffer + (Destination.Y + Line) * DestStride;
+ DestAddr = (UINT8*)DestAddr + Destination.X * Display->Bpp;
+ CopyBytes = Source.Width * Display->Bpp;
+ CopyMem (DestAddr, SourceAddr, CopyBytes);
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "EfiBltVideoToBltBuffer [%d, %d] >> [%d, %d] size [%d, %d] Delta %d\n",
+ Source.X, Source.Y,
+ Destination.X, Destination.Y,
+ Source.Width, Source.Height,
+ Delta
+ );
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFromBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *SourceAddr, *DestAddr;
+ UINTN SourceStride, CopyBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Source.Width == 0 || Source.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltBufferToVideo invalid source rectangle [%d, %d] \n",
+ Source.Width, Source.Height
+ );
+ goto Done;
+ }
+
+ if (Source.Width != Destination.Width || Source.Height != Destination.Height) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltBufferToVideo size mismatch: source %dx%d, destination %dx%d\n",
+ Source.Width, Source.Height, Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Destination.X + Destination.Width > Display->Width) ||
+ (Destination.Y + Destination.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltBufferToVideo destination [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Destination.X, Destination.Y,
+ Destination.X + Destination.Width, Destination.Y + Destination.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Source.X != 0 || Source.Y != 0) {
+ SourceStride = Delta;
+ } else {
+ SourceStride = Source.Width * Display->Bpp;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ for (Line = 0; Line < Source.Height; Line++) {
+ SourceAddr = (UINT8*)BltBuffer +
+ (Source.Y + Line) * SourceStride +
+ Source.X * Display->Bpp;
+ DestAddr = (UINT8*)Display->FbGMAddr +
+ (Destination.Y + Line) * ModeStrideBytes +
+ Destination.X * Display->Bpp;
+ CopyBytes = Source.Width * Display->Bpp;
+ CopyMem (DestAddr, SourceAddr, CopyBytes);
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "EfiBltBufferToVideo [%d, %d] >> [%d, %d] size [%d, %d] Delta %d\n",
+ Source.X, Source.Y,
+ Destination.X, Destination.Y,
+ Source.Width, Source.Height,
+ Delta
+ );
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToVideo (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ VOID *SourceAddr, *DestAddr;
+ UINTN CopyBytes, ModeStrideBytes, Line;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ if (Source.Width == 0 || Source.Height == 0) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo invalid source rectangle [%d, %d] \n",
+ Source.Width, Source.Height
+ );
+ goto Done;
+ }
+
+ if (Source.Width != Destination.Width || Source.Height != Destination.Height) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo size mismatch: source %dx%d, destination %dx%d\n",
+ Source.Width, Source.Height, Destination.Width, Destination.Height
+ );
+ goto Done;
+ }
+
+ if ((Source.X + Source.Width > Display->Width) ||
+ (Source.Y + Source.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo source [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Source.X, Source.Y,
+ Source.X + Source.Width, Source.Y + Source.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if ((Destination.X + Destination.Width > Display->Width) ||
+ (Destination.Y + Destination.Height > Display->Height)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "EfiBltVideoToVideo destination [%d, %d] to [%d, %d] ouf of range [%d, %d]\n",
+ Destination.X, Destination.Y,
+ Destination.X + Destination.Width, Destination.Y + Destination.Height,
+ Display->Width, Display->Height
+ );
+ goto Done;
+ }
+
+ if (Display->CurrentMode == DISPLAY_MODE_INVALID) {
+ ModeStrideBytes = Display->Width;
+ } else {
+ ModeStrideBytes = Display->ModeList[Display->CurrentMode].HorizontalResolution;
+ }
+ ModeStrideBytes = ALIGN_VALUE (ModeStrideBytes * Display->Bpp, 64);
+
+ for (Line = 0; Line < Source.Height; Line++) {
+ SourceAddr = (UINT8*)Display->FbGMAddr +
+ (Source.Y + Line) * ModeStrideBytes +
+ Source.X * Display->Bpp;
+ DestAddr = (UINT8*)Display->FbGMAddr +
+ (Destination.Y + Line)* ModeStrideBytes +
+ Destination.X * Display->Bpp;
+ CopyBytes = Source.Width * Display->Bpp;
+ //
+ // Overlap could corrupt source content:
+ // src <----|---->
+ // dst <----|---->
+ //
+ if (DestAddr > SourceAddr && DestAddr < (SourceAddr + CopyBytes)) {
+ CopyMem (
+ SourceAddr + CopyBytes,
+ DestAddr,
+ SourceAddr + CopyBytes - DestAddr
+ );
+ CopyMem (DestAddr, SourceAddr, DestAddr - SourceAddr);
+ //
+ // Overlap won't corrupt source content:
+ // src <----|---->
+ // dst <----|---->
+ //
+ // No overlap
+ // src <--------->
+ // dst <--------->
+ //
+ } else {
+ CopyMem (DestAddr, SourceAddr, CopyBytes);
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/Display.h b/OvmfPkg/IntelGvtGopDxe/Display.h
new file mode 100644
index 000000000000..19e4d64f3b12
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Display.h
@@ -0,0 +1,141 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __DISPLAY_H_
+#define __DISPLAY_H_
+
+#include <Library/FrameBufferBltLib.h>
+
+typedef struct _BLT_RECTANGLE {
+ UINTN X;
+ UINTN Y;
+ UINTN Width;
+ UINTN Height;
+} BLT_RECTANGLE, *PBLT_RECTANGLE;
+
+#define DISPLAY_WIDTH_MAX 1920
+#define DISPLAY_HEIGHT_MAX 1080
+#define DISPLAY_WIDTH_DEFAULT 1024
+#define DISPLAY_HEIGHT_DEFAULT 768
+#define DISPLAY_MODE_INVALID 0xFFFF
+
+#define DISPLAY_USE_INTERNAL_BLT 1
+
+typedef struct _INTEL_VIRTUAL_GPU_DISPLAY {
+ UINTN HActive;
+ UINTN VActive;
+ UINTN Width;
+ UINTN Height;
+ UINTN WidthBytes;
+ UINTN StrideBytes;
+ EFI_GRAPHICS_PIXEL_FORMAT Format;
+ UINTN Bpp;
+ UINTN MaxMode;
+ UINTN CurrentMode;
+ UINTN FbSize;
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS FbGMAddr;
+ EFI_PHYSICAL_ADDRESS FbPhysicalAddr;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeList;
+ FRAME_BUFFER_CONFIGURE *FrameBufferBltConfigure;
+ UINTN FrameBufferBltConfigureSize;
+} INTEL_VIRTUAL_GPU_DISPLAY, *PINTEL_VIRTUAL_GPU_DISPLAY;
+
+EFI_STATUS
+IntelVirtualGpuDisplayInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+IntelVirtualGpuDisplayClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuQueryMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ );
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ );
+
+EFI_STATUS
+EFIAPI
+IntelVirtualGpuBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ );
+
+EFI_STATUS
+IntelVirtualGpuEnableDisplay (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 ModeNumber,
+ IN BOOLEAN Enable
+ );
+
+EFI_STATUS
+IntelVirtualGpuNotifyDisplayReady (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN BOOLEAN Ready
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFill (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltPixel,
+ IN BLT_RECTANGLE Destination
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoFromBuffer (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination,
+ IN UINTN Delta
+ );
+
+EFI_STATUS
+IntelVirtualGpuBltVideoToVideo (
+ IN PINTEL_VIRTUAL_GPU_DISPLAY Display,
+ IN BLT_RECTANGLE Source,
+ IN BLT_RECTANGLE Destination
+ );
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ );
+
+#endif //__DISPLAY_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/GopDriver.c b/OvmfPkg/IntelGvtGopDxe/GopDriver.c
new file mode 100644
index 000000000000..396e5cf4447c
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/GopDriver.c
@@ -0,0 +1,478 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "VirtualGpu.h"
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gGvtGopDriverComponentName = {
+ GvtGopComponentNameGetDriverName,
+ GvtGopComponentNameGetControllerName,
+ "eng"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gGvtGopDriverComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GvtGopComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GvtGopComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE gGvtGopDriverNameTable[] = {
+ { "eng;en", L"Intel GVT-g GOP Driver" },
+ { NULL , NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE gGvtGopControllerNameTable[] = {
+ { "eng;en", L"Intel GVT-g Virtual GPU PCI Adapter" },
+ { NULL , NULL }
+};
+
+STATIC
+EFI_STATUS
+EFIAPI
+GvtGopBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "OpenProtocol gEfiPciIoProtocolGuid failed with %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = IntelVirtualGpuActive (PciIo);
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+Done:
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+GvtGopBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OriginalTPL;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+ UINT64 PciAttr;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
+ EFI_PCI_IO_PROTOCOL *ChildPciIo;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ OriginalTPL = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(GVT_GOP_PRIVATE_DATA),
+ (VOID **)&GvtGopPrivate
+ );
+ if (EFI_ERROR (Status) || GvtGopPrivate == NULL) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for GVT_GOP_PRIVATE_DATA, size %d, status %d\n",
+ sizeof(GVT_GOP_PRIVATE_DATA), Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ZeroMem (GvtGopPrivate, sizeof(GVT_GOP_PRIVATE_DATA));
+ GvtGopPrivate->Signature = GVT_GOP_MAGIC;
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(INTEL_VIRTUAL_GPU),
+ &GvtGopPrivate->VirtualGpu
+ );
+ if (EFI_ERROR (Status) || GvtGopPrivate->VirtualGpu == NULL) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "AllocatePool failed for INTEL_VIRTUAL_GPU, size %d, status %d\n",
+ sizeof(INTEL_VIRTUAL_GPU), Status
+ );
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Free;
+ }
+ ZeroMem (GvtGopPrivate->VirtualGpu, sizeof(INTEL_VIRTUAL_GPU));
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &GvtGopPrivate->PciIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't open protocol gEfiPciIoProtocolGuid, status %d\n", Status
+ );
+ goto Free;
+ }
+
+ Status = GvtGopPrivate->PciIo->Attributes (
+ GvtGopPrivate->PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &GvtGopPrivate->OriginalPciAttr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed EfiPciIoAttributeOperationGet, status %d\n", Status
+ );
+ goto Free;
+ }
+
+ PciAttr = EFI_PCI_DEVICE_ENABLE;
+ Status = GvtGopPrivate->PciIo->Attributes (
+ GvtGopPrivate->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ PciAttr,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed EfiPciIoAttributeOperationEnable %llx, status %d\n", PciAttr,
+ Status
+ );
+ goto Free;
+ }
+
+ Status = IntelVirtualGpuInit (GvtGopPrivate);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Failed IntelVirtualGpuInit, status %d\n", Status);
+ goto Free;
+ }
+
+ Status = gBS->HandleProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Fail gEfiDevicePathProtocolGuid, status %d\n",
+ Status
+ );
+ goto Free;
+ }
+
+ ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
+ AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
+ AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
+ AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, 0, 0);
+ SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+ GvtGopPrivate->GopDevPath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
+ );
+ if (GvtGopPrivate->GopDevPath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR, "Fail AppendDevicePathNode, status %d\n", Status);
+ goto Free;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &GvtGopPrivate->Handle,
+ &gEfiDevicePathProtocolGuid,
+ GvtGopPrivate->GopDevPath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't install protocol gEfiDevicePathProtocolGuid, status %d\n",
+ Status
+ );
+ goto Free;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &GvtGopPrivate->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &GvtGopPrivate->GraphicsOutputProtocol,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't install protocol gEfiGraphicsOutputProtocolGuid, status %d\n",
+ Status
+ );
+ goto Free;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &ChildPciIo,
+ This->DriverBindingHandle,
+ GvtGopPrivate->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Free;
+ }
+
+ goto Done;
+
+Free:
+ if (GvtGopPrivate->PciIo) {
+ if (GvtGopPrivate->OriginalPciAttr) {
+ GvtGopPrivate->PciIo->Attributes (
+ GvtGopPrivate->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ GvtGopPrivate->OriginalPciAttr,
+ NULL
+ );
+ }
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ GvtGopPrivate->PciIo = NULL;
+ }
+
+ if (GvtGopPrivate->VirtualGpu) {
+ gBS->FreePool (GvtGopPrivate->VirtualGpu);
+ GvtGopPrivate->VirtualGpu = NULL;
+ }
+
+ if (GvtGopPrivate) {
+ gBS->FreePool (GvtGopPrivate);
+ }
+
+ if (GvtGopPrivate->GopDevPath) {
+ FreePool (GvtGopPrivate->GopDevPath);
+ GvtGopPrivate->GopDevPath = NULL;
+ }
+
+Done:
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+GvtGopBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutputProtocol;
+ EFI_STATUS Status;
+ GVT_GOP_PRIVATE_DATA *GvtGopPrivate = NULL;
+
+ GVT_DEBUG (EFI_D_INFO, "%a: >>>\n", __FUNCTION__);
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **)&GraphicsOutputProtocol,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_STARTED;
+ goto Done;
+ }
+
+ GvtGopPrivate = GVT_GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutputProtocol);
+ if (!GvtGopPrivate) {
+ Status = EFI_NOT_STARTED;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Intel GVT-g GOP isn't started, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ GvtGopPrivate->Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &GvtGopPrivate->GraphicsOutputProtocol,
+ NULL
+ );
+
+ if (GvtGopPrivate->PciIo) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ GvtGopPrivate->PciIo = NULL;
+ }
+
+ Status = IntelVirtualGpuClean (GvtGopPrivate);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Fail to clean virtual GPU, status %d\n", Status);
+ goto Done;
+ }
+
+ if (GvtGopPrivate->VirtualGpu) {
+ gBS->FreePool (GvtGopPrivate->VirtualGpu);
+ GvtGopPrivate->VirtualGpu = NULL;
+ }
+
+ if (GvtGopPrivate) {
+ gBS->FreePool (GvtGopPrivate);
+ }
+
+Done:
+
+ GVT_DEBUG (EFI_D_INFO, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+STATIC EFI_DRIVER_BINDING_PROTOCOL gGvtGopDriverBinding = {
+ GvtGopBindingSupported,
+ GvtGopBindingStart,
+ GvtGopBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ gGvtGopDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gGvtGopDriverComponentName)
+ );
+}
+
+EFI_STATUS
+EFIAPI
+GvtGopComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gGvtGopDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ gGvtGopControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gGvtGopDriverComponentName)
+ );
+}
+
+EFI_STATUS
+EFIAPI
+GvtGopEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gGvtGopDriverBinding,
+ ImageHandle,
+ &gGvtGopDriverComponentName,
+ &gGvtGopDriverComponentName2);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Failed to install driver %d : %d\n", Status);
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/GpuReg.c b/OvmfPkg/IntelGvtGopDxe/GpuReg.c
new file mode 100644
index 000000000000..778c09d5198c
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/GpuReg.c
@@ -0,0 +1,91 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GpuReg.h"
+
+EFI_STATUS
+RegRead32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ OUT UINT32 *ValuePtr
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+
+ if (Offset < MMIO_SIZE && ValuePtr != NULL) {
+ Status = Private->PciIo->Mem.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ Offset,
+ 1,
+ ValuePtr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, *ValuePtr, Status
+ );
+ } else {
+ Status = EFI_SUCCESS;
+ GVT_DEBUG (EFI_D_VERBOSE, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, *ValuePtr, Status
+ );
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR,
+ "%a invalid reg %x or ValuePtr %p, status %d\n",
+ __FUNCTION__, Offset, ValuePtr, Status
+ );
+ goto Done;
+ }
+
+Done:
+ return Status;
+}
+
+EFI_STATUS
+RegWrite32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+
+ if (Offset < MMIO_SIZE) {
+ Status = Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ Offset,
+ 1,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, Value, Status
+ );
+ } else {
+ Status = EFI_SUCCESS;
+ GVT_DEBUG (EFI_D_VERBOSE, "%a reg %x, value %x, status %d\n",
+ __FUNCTION__, Offset, Value, Status
+ );
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR, "%a invalid reg %x, status %d\n",
+ __FUNCTION__, Offset, Status
+ );
+ goto Done;
+ }
+
+Done:
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/GpuReg.h b/OvmfPkg/IntelGvtGopDxe/GpuReg.h
new file mode 100644
index 000000000000..f46f4cef9cd4
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/GpuReg.h
@@ -0,0 +1,175 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __GPUREG_H_
+#define __GPUREG_H_
+
+#include "Common.h"
+
+#define MMIO_SIZE 0x200000
+
+#define VGT_PVINFO_PAGE 0x78000
+#define VGT_PVINFO_SIZE 0x1000
+
+#define VGT_MAGIC 0x4776544776544776ULL /* 'vGTvGTvG' */
+#define VGT_VERSION_MAJOR 1
+#define VGT_VERSION_MINOR 0
+
+#define VGT_DRV_DISPLAY_NOT_READY 0
+#define VGT_DRV_DISPLAY_READY 1
+
+struct vgt_if {
+ UINT64 magic; /* VGT_MAGIC */
+ UINT16 version_major;
+ UINT16 version_minor;
+ UINT32 vgt_id; /* ID of vGT instance */
+ UINT32 vgt_caps; /* VGT capabilities */
+ UINT32 rsv1[11]; /* pad to offset 0x40 */
+ /*
+ * Data structure to describe the balooning info of resources.
+ * Each VM can only have one portion of continuous area for now.
+ * (May support scattered resource in future)
+ * (starting from offset 0x40)
+ */
+ struct {
+ /* Aperture register balooning */
+ struct {
+ UINT32 base;
+ UINT32 size;
+ } mappable_gmadr; /* aperture */
+ /* GMADR register balooning */
+ struct {
+ UINT32 base;
+ UINT32 size;
+ } nonmappable_gmadr; /* non aperture */
+ /* allowed fence registers */
+ UINT32 fence_num;
+ UINT32 rsv2[3];
+ } avail_rs; /* available/assigned resource */
+ UINT32 rsv3[0x200 - 24]; /* pad to half page */
+ /*
+ * The bottom half page is for response from Gfx driver to hypervisor.
+ */
+ UINT32 rsv4;
+ UINT32 display_ready; /* ready for display owner switch */
+
+ UINT32 rsv5[4];
+
+ UINT32 g2v_notify;
+ UINT32 rsv6[5];
+
+ UINT32 cursor_x_hot;
+ UINT32 cursor_y_hot;
+
+ struct {
+ UINT32 lo;
+ UINT32 hi;
+ } pdp[4];
+
+ UINT32 execlist_context_descriptor_lo;
+ UINT32 execlist_context_descriptor_hi;
+
+ UINT32 rsv7[0x200 - 24]; /* pad to one page */
+} PACKED;
+
+#define vgtif_offset(x) (OFFSET_OF(struct vgt_if, x))
+#define vgtif_reg(x) (VGT_PVINFO_PAGE + vgtif_offset(x))
+
+typedef enum _GPU_DISPLAY_PIPE {
+ PIPE_INVALID = -1,
+ PIPE_A = 0,
+ PIPE_B,
+ PIPE_C,
+ PIPE_MAX = PIPE_C
+} GPU_DISPLAY_PIPE;
+
+typedef enum _GPU_DISPLAY_PLANE {
+ PLANE_PRIMARY = 0,
+ PLANE_SPRITE0,
+ PLANE_SPRITE1,
+ PLANE_MAX,
+} GPU_DISPLAY_PLANE;
+
+#define _TRANS_HTOTAL_A 0x60000
+#define _TRANS_VTOTAL_A 0x6000C
+#define _TRANS_REG_OFFSET(trans) (trans * 0x1000)
+
+#define _PS_WIN_POS_1_A 0x68170
+#define _PS_WIN_SZ_1_A 0x68174
+#define _PS_CTRL_1_A 0x68180
+#define _PS_REG_OFFSET(pipe, id) (pipe * 0x800 + id * 0x100)
+#define PS_WIN_POS(pipe, id) (_PS_WIN_POS_1_A + _PS_REG_OFFSET(pipe, id))
+#define PS_WIN_SZ(pipe, id) (_PS_WIN_SZ_1_A + _PS_REG_OFFSET(pipe, id))
+#define PS_CTRL(pipe, id) (_PS_CTRL_1_A + _PS_REG_OFFSET(pipe, id))
+#define PS_CTRL_SCALER_EN (1 << 31)
+#define PS_CTRL_SCALER_MODE_MASK (0x3 << 28)
+#define PS_CTRL_SCALER_MODE_DYN (0 << 28)
+#define PS_CTRL_SCALER_MODE_HQ (1 << 28)
+#define PS_CTRL_SCALER_BINDING_MASK (0x7 << 25)
+#define PS_CTRL_SCALER_BINDING_PIPE (0 << 25)
+#define PS_CTRL_PLANE_SEL(plane) (((plane) + 1) << 25)
+#define PS_CTRL_SCALER_FILTER_MASK (3 << 23)
+#define PS_CTRL_SCALER_FILTER_MEDIUM (0 << 23)
+
+#define PIPE_REG_OFFSET(pipe) (pipe * 0x1000)
+#define _PIPE_CONF_A 0x70008
+#define PIPE_CONF_ENABLE (1 << 31)
+#define _PIPE_SRCSZ_A 0x6001C
+#define PIPE_CONF(pipe) (_PIPE_CONF_A + PIPE_REG_OFFSET(pipe))
+#define PIPESRC(pipe) (_PIPE_SRCSZ_A + PIPE_REG_OFFSET(pipe))
+
+#define _PLANE_CTL_1_A 0x70180
+#define PLANE_CTL_ENABLE (1 << 31)
+#define PLANE_CTL_PIPE_GAMMA_ENABLE (1 << 30)
+#define PLANE_CTL_FORMAT_MASK (0xF << 24)
+#define PLANE_CTL_FORMAT_XRGB_8888 (0x4 << 24)
+#define PLANE_CTL_PIPE_CSC_ENABLE (1 << 23)
+#define PLANE_CTL_KEY_ENABLE_MASK (0x3 << 21)
+#define PLANE_CTL_ORDER_RGBX (1 << 20)
+#define PLANE_CTL_RENDER_DECOMPRESSION_ENABLE (1 << 15)
+#define PLANE_CTL_PLANE_GAMMA_DISABLE (1 << 13)
+#define PLANE_CTL_TILED_MASK (0x7 << 10)
+#define PLANE_CTL_TILED_LINEAR (0 << 10)
+#define PLANE_CTL_ASYNC_FLIP (1 << 9)
+#define PLANE_CTL_ALPHA_MASK (0x3 << 4)
+#define PLANE_CTL_ALPHA_DISABLE (0 << 4)
+#define PLANE_CTL_ROTATE_MASK (0x3 << 0)
+#define PLANE_CTL_ROTATE_0 (0x0 << 0)
+
+#define _PLANE_STRIDE_1_A 0x70188
+#define PLANE_STRIDE_MASK 0x1FF
+#define _PLANE_POS_1_A 0x7018C
+#define _PLANE_SIZE_1_A 0x70190
+#define _PLANE_SURF_1_A 0x7019C
+#define _PLANE_REG_OFFSET(pipe, plane) (pipe * 0x1000 + plane * 0x100)
+
+#define HTOTAL(trans) (_TRANS_HTOTAL_A + _TRANS_REG_OFFSET(trans))
+#define VTOTAL(trans) (_TRANS_VTOTAL_A + _TRANS_REG_OFFSET(trans))
+
+#define PLANE_CTL(pipe, plane) (_PLANE_CTL_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_STRIDE(pipe, plane) (_PLANE_STRIDE_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_POS(pipe, plane) (_PLANE_POS_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_SIZE(pipe, plane) (_PLANE_SIZE_1_A + _PLANE_REG_OFFSET(pipe, plane))
+#define PLANE_SURF(pipe, plane) (_PLANE_SURF_1_A + _PLANE_REG_OFFSET(pipe, plane))
+
+EFI_STATUS
+RegRead32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ OUT UINT32 *ValuePtr
+ );
+
+EFI_STATUS
+RegWrite32 (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT32 Offset,
+ IN UINT32 Value
+ );
+
+#endif //__GPUREG_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/Gtt.c b/OvmfPkg/IntelGvtGopDxe/Gtt.c
new file mode 100644
index 000000000000..12782eb5afaa
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Gtt.c
@@ -0,0 +1,162 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "Gtt.h"
+#include "VirtualGpu.h"
+
+EFI_STATUS
+GGTTGetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ OUT GTT_PTE_ENTRY *Entry
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+
+ if (Entry == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR,
+ "%a invalid GGTT entry ptr %p at Index %x, status %d\n",
+ __FUNCTION__, Entry, Index, Status
+ );
+ goto Done;
+ }
+
+ PciIo = Private->PciIo;
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+
+ if (Index >= VirtualGpu->VisibleGGTTOffset &&
+ Index < VirtualGpu->VisibleGGTTOffset + VirtualGpu->VisibleGGTTSize) {
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BAR_IDX0,
+ GTT_OFFSET + Index * GTT_ENTRY_SIZE,
+ 1,
+ Entry
+ );
+ if (EFI_ERROR (Status)) {
+ Entry = 0;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed to Get GGTT Entry index %lx, status %d\n", Index, Status
+ );
+ }
+ } else if (Index >= VirtualGpu->InvisibleGGTTOffset &&
+ Index < VirtualGpu->InvisibleGGTTOffset + VirtualGpu->InvisibleGGTTSize) {
+ Status = EFI_UNSUPPORTED;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip get GGTT index %lx for invisible GMADR\n", Index
+ );
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip get GGTT index %lx out-of-range, balloon unsupported\n",
+ Index
+ );
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "Get GGTT Entry %lx at index %lx\n", *Entry, Index);
+
+Done:
+
+ return Status;
+}
+
+EFI_STATUS
+GGTTSetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ IN GTT_PTE_ENTRY Entry
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+
+ PciIo = Private->PciIo;
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+
+ if (Index >= VirtualGpu->VisibleGGTTOffset &&
+ Index < VirtualGpu->VisibleGGTTOffset + VirtualGpu->VisibleGGTTSize) {
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BAR_IDX0,
+ GTT_OFFSET + Index * GTT_ENTRY_SIZE,
+ 1,
+ &Entry
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed to Set GGTT Entry %lx at index %lx, status %d\n",
+ Entry, Index, Status
+ );
+ }
+ } else if (Index >= VirtualGpu->InvisibleGGTTOffset &&
+ Index < VirtualGpu->InvisibleGGTTOffset + VirtualGpu->InvisibleGGTTSize) {
+ Status = EFI_UNSUPPORTED;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip set GGTT index %lx for invisible GMADR\n", Index
+ );
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Skip set GGTT index %lx out-of-range, balloon unsupported\n", Index
+ );
+ }
+
+ GVT_DEBUG (EFI_D_VERBOSE, "Set GGTT Entry %lx at index %lx\n", Entry, Index);
+
+ return Status;
+}
+
+EFI_STATUS
+UpdateGGTT (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN EFI_PHYSICAL_ADDRESS GMAddr,
+ IN EFI_PHYSICAL_ADDRESS SysAddr,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ UINTN GttOffset, Index;
+ GTT_PTE_ENTRY Entry;
+
+ if (!IS_ALIGNED(SysAddr, GTT_PAGE_SIZE)) {
+ Status = EFI_INVALID_PARAMETER;
+ GVT_DEBUG (EFI_D_ERROR,
+ "Failed to update GGTT GMADR %lx, SysAddr %lx isn't aligned to 0x%lx, status %d\n",
+ GMAddr, SysAddr, GTT_PAGE_SIZE, Status
+ );
+ goto Done;
+ }
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ GttOffset = (GMAddr - VirtualGpu->GpuMemAddr) >> GTT_PAGE_SHIFT;
+
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "Update GGTT GMADR %lx, SysAddr %lx, Pages 0x%lx\n",
+ GMAddr, SysAddr, Pages
+ );
+ for (Index = 0; Index < Pages; Index++) {
+ Entry = SysAddr + Index * GTT_PAGE_SIZE;
+ Entry |= (GTT_PAGE_PRESENT | GTT_PAGE_READ_WRITE);
+ Entry |= (GTT_PAGE_PWT | GTT_PAGE_PCD);
+ GGTTSetEntry (Private, GttOffset + Index, Entry);
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/Gtt.h b/OvmfPkg/IntelGvtGopDxe/Gtt.h
new file mode 100644
index 000000000000..fc91b7a84a0a
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Gtt.h
@@ -0,0 +1,51 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __GTT_H_
+#define __GTT_H_
+
+#include "Common.h"
+
+typedef UINT64 GTT_PTE_ENTRY;
+
+#define GTT_OFFSET 0x800000
+#define GTT_SIZE 0x800000
+#define GTT_ENTRY_SIZE sizeof(GTT_PTE_ENTRY)
+#define GTT_ENTRY_NUM (GTT_SIZE / GTT_ENTRY_SIZE)
+#define GTT_PAGE_SHIFT 12
+#define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT)
+#define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1))
+#define GTT_PAGE_PRESENT 0x01
+#define GTT_PAGE_READ_WRITE 0x02
+#define GTT_PAGE_PWT 0x08
+#define GTT_PAGE_PCD 0x10
+
+EFI_STATUS
+GGTTGetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ OUT GTT_PTE_ENTRY *Entry
+ );
+
+EFI_STATUS
+GGTTSetEntry (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN UINT64 Index,
+ IN GTT_PTE_ENTRY Entry
+ );
+
+EFI_STATUS
+UpdateGGTT (
+ IN GVT_GOP_PRIVATE_DATA *Private,
+ IN EFI_PHYSICAL_ADDRESS GMAddr,
+ IN EFI_PHYSICAL_ADDRESS SysAddr,
+ IN UINTN Pages
+ );
+
+#endif //__GTT_H_
diff --git a/OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf b/OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf
new file mode 100644
index 000000000000..c6e1751e1a22
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/IntelGvtGopDxe.inf
@@ -0,0 +1,59 @@
+## @file
+# Intel GVT-g Graphics Output Protocol driver
+#
+# Copyright (C) 2021 Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = GvtGopDxe
+ FILE_GUID = 7c2a0c14-2a63-4d08-9c7f-d55691e1cedb
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 2.0
+ ENTRY_POINT = GvtGopEntryPoint
+
+[Sources]
+ Common.h
+ DebugHelper.h
+ Display.c
+ Display.h
+ GopDriver.c
+ GpuReg.c
+ GpuReg.h
+ Gtt.c
+ Gtt.h
+ VirtualGpu.h
+ VirtualGpu.c
+ VbeShim.c
+ VbeShim.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ FrameBufferBltLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ PcdLib
+ PciLib
+ QemuFwCfgLib
+
+[Protocols]
+ gEfiGraphicsOutputProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.asm b/OvmfPkg/IntelGvtGopDxe/VbeShim.asm
new file mode 100644
index 000000000000..43a44362b794
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.asm
@@ -0,0 +1,343 @@
+;------------------------------------------------------------------------------
+; @file
+; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's buggy,
+; default VGA driver to switch to 1024x768x32.
+;
+; Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+; Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+; Copyright (C) 2015, Nahanni Systems, Inc.
+; Copyright (C) 2014, Red Hat, Inc.
+; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+; enable this macro for debug messages
+%define DEBUG
+
+%macro DebugLog 1
+%ifdef DEBUG
+ push si
+ mov si, %1
+ call PrintStringSi
+ pop si
+%endif
+%endmacro
+
+
+BITS 16
+ORG 0
+
+VbeInfo:
+TIMES 256 nop
+
+VbeModeInfo:
+VbeMode1:
+TIMES 50 nop
+VbeMode2:
+TIMES 50 nop
+VbeMode3:
+TIMES 50 nop
+VbeMode4:
+TIMES 50 nop
+TIMES 56 nop ; filler for 256 bytes
+
+Handler:
+ cmp ax, 0x4f00
+ je GetInfo
+ cmp ax, 0x4f01
+ je GetModeInfo
+ cmp ax, 0x4f02
+ je SetMode
+ cmp ax, 0x4f03
+ je GetMode
+ cmp ax, 0x4f10
+ je GetPmCapabilities
+ cmp ax, 0x4f15
+ je ReadEdid
+ cmp ah, 0x00
+ je SetModeLegacy
+ DebugLog StrUnkownFunction
+Hang:
+ jmp Hang
+
+
+GetInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetInfo
+
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, VbeInfo
+ ; source (ds:si) set now
+
+ mov cx, 256
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+GetModeInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetModeInfo
+
+ and cx, ~0x4000 ; clear potentially set LFB bit in mode number
+
+ cmp cx, 0x013f
+ je gKnownMode1
+ cmp cx, 0x0140
+ je gKnownMode2
+ cmp cx, 0x0141
+ je gKnownMode3
+
+ DebugLog StrUnkownMode
+ jmp Hang
+gKnownMode1:
+ DebugLog StrMode1
+ mov si, VbeMode1
+ jmp CopyModeInfo
+gKnownMode2:
+ DebugLog StrMode2
+ mov si, VbeMode2
+ jmp CopyModeInfo
+gKnownMode3:
+ DebugLog StrMode3
+ mov si, VbeMode3
+ jmp CopyModeInfo
+gKnownMode4:
+ DebugLog StrMode4
+ mov si, VbeMode4
+ jmp CopyModeInfo
+
+CopyModeInfo:
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ ;mov si, VbeModeInfo
+ ; source (ds:si) set now
+
+ ;mov cx, 256
+ mov cx, 50
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+SetMode:
+ push dx
+ push ax
+
+ DebugLog StrEnterSetMode
+
+ and bx, ~0x4000 ; clear potentially set LFB bit in mode number
+ cmp bx, 0x013f
+ je KnownMode1
+ cmp bx, 0x0140
+ je KnownMode2
+ cmp bx, 0x0141
+ je KnownMode3
+ DebugLog StrUnkownMode
+ jmp Hang
+KnownMode1:
+ DebugLog StrMode1
+ jmp SetModeDone
+KnownMode2:
+ DebugLog StrMode2
+ jmp SetModeDone
+KnownMode3:
+ DebugLog StrMode3
+ jmp SetModeDone
+KnownMode4:
+ DebugLog StrMode4
+
+SetModeDone:
+ mov [CurMode], bl
+ mov [CurMode+1], bh
+ pop ax
+ pop dx
+ jmp Success
+
+
+GetMode:
+ DebugLog StrEnterGetMode
+ mov bl, [CurMode]
+ mov bh, [CurMode+1]
+ jmp Success
+
+
+GetPmCapabilities:
+ DebugLog StrGetPmCapabilities
+ mov bx, 0x0080
+ jmp Success
+
+
+ReadEdid:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrReadEdid
+
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, Edid
+ ; source (ds:si) set now
+
+ mov cx, 128
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+SetModeLegacy:
+ DebugLog StrEnterSetModeLegacy
+
+ cmp al, 0x03
+ je sKnownMode3
+ cmp al, 0x12
+ je sKnownMode4
+ DebugLog StrUnkownMode
+ jmp Hang
+sKnownMode3:
+ DebugLog StrLegacyMode3
+ mov al, 0 ; 0x30
+ jmp SetModeLegacyDone
+sKnownMode4:
+ mov al, 0 ;0x20
+SetModeLegacyDone:
+ DebugLog StrExitSuccess
+ iret
+
+
+Success:
+ DebugLog StrExitSuccess
+ mov ax, 0x004f
+ iret
+
+
+Unsupported:
+ DebugLog StrExitUnsupported
+ mov ax, 0x024f
+ iret
+
+
+%ifdef DEBUG
+PrintStringSi:
+ pusha
+ push ds ; save original
+ push cs
+ pop ds
+ mov dx, 0x220 ; bhyve debug cons port
+ mov ax, 0
+PrintStringSiLoop:
+ lodsb
+ cmp al, 0
+ je PrintStringSiDone
+ out dx, al
+ jmp PrintStringSiLoop
+PrintStringSiDone:
+ pop ds ; restore original
+ popa
+ ret
+
+
+StrExitSuccess:
+ db 'vOk', 0x0d, 0x0a, 0
+
+StrExitUnsupported:
+ db 'vUnsupported', 0x0d, 0x0a, 0
+
+StrUnkownFunction:
+ db 'vUnknown Function', 0x0d, 0x0a, 0
+
+StrEnterGetInfo:
+ db 'vGetInfo', 0x0d, 0x0a, 0
+
+StrEnterGetModeInfo:
+ db 'vGetModeInfo', 0x0d, 0x0a, 0
+
+StrEnterGetMode:
+ db 'vGetMode', 0x0d, 0x0a, 0
+
+StrEnterSetMode:
+ db 'vSetMode', 0x0d, 0x0a, 0
+
+StrEnterSetModeLegacy:
+ db 'vSetModeLegacy', 0x0d, 0x0a, 0
+
+StrUnkownMode:
+ db 'vUnkown Mode', 0x0d, 0x0a, 0
+
+StrGetPmCapabilities:
+ db 'vGetPmCapabilities', 0x0d, 0x0a, 0
+
+StrReadEdid:
+ db 'vReadEdid', 0x0d, 0x0a, 0
+
+StrLegacyMode3:
+ db 'vLegacyMode3', 0x0d, 0x0a, 0
+
+
+StrMode1:
+ db 'mode_640x480x32', 0x0d, 0x0a, 0
+StrMode2:
+ db 'mode_800x600x32', 0x0d, 0x0a, 0
+StrMode3:
+ db 'mode_1024x768x32', 0x0d, 0x0a, 0
+StrMode4:
+ db 'mode_unused', 0x0d, 0x0a, 0
+%endif
+
+CurMode:
+ db 0x00, 0x00
+
+;
+; EDID stores monitor information. For now, just send back an null item.
+;
+Edid:
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.c b/OvmfPkg/IntelGvtGopDxe/VbeShim.c
new file mode 100644
index 000000000000..8063224d53b4
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.c
@@ -0,0 +1,258 @@
+/** @file
+ Install a fake VGABIOS service handler (real mode Int10h) for the buggy
+ Windows 2008 R2 SP1 UEFI guest.
+
+ The handler is never meant to be directly executed by a VCPU; it's there for
+ the internal real mode emulator of Windows 2008 R2 SP1.
+
+ The code is based on Ralf Brown's Interrupt List:
+ <http://www.cs.cmu.edu/~ralf/files.html>
+ <http://www.ctyme.com/rbrown.htm>
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (C) 2015, Nahanni Systems, Inc.
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include <IndustryStandard/LegacyVgaBios.h>
+#include <Library/PciLib.h>
+#include <Library/PrintLib.h>
+#include "VbeShim.h"
+
+#pragma pack (1)
+typedef struct {
+ UINT16 Offset;
+ UINT16 Segment;
+} IVT_ENTRY;
+#pragma pack ()
+
+//
+// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
+// Advanced Settings dialog. It should be short.
+//
+STATIC CONST CHAR8 mProductRevision[] = "2.0";
+
+#define NUM_VBE_MODES 3
+STATIC CONST UINT16 vbeModeIds[] = {
+ 0x13f, // 640x480x32
+ 0x140, // 800x600x32
+ 0x141 // 1024x768x32
+};
+
+// Modes can be toggled with bit-0
+#define VBE_MODE_ENABLED 0x00BB
+#define VBE_MODE_DISABLED 0x00BA
+
+STATIC VBE2_MODE_INFO vbeModes[] = {
+ { // 0x13f 640x480x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 640*4,
+ // Width, Height..., Vbe3
+ 640, 480, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ },
+ { // 0x140 800x600x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 800*4,
+ // Width, Height..., Vbe3
+ 800, 600, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ },
+ { // 0x141 1024x768x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_ENABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 1024*4,
+ // Width, Height..., Vbe3
+ 1024, 768, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ }
+};
+
+/**
+ Install the VBE Info and VBE Mode Info structures, and the VBE service
+ handler routine in the C segment. Point the real-mode Int10h interrupt vector
+ to the handler. The only advertised mode is 1024x768x32.
+
+ @param[in] CardName Name of the video card to be exposed in the
+ Product Name field of the VBE Info structure.
+ @param[in] FrameBufferBase Guest-physical base address of the video card's
+ frame buffer.
+**/
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ )
+{
+ EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
+ UINTN Segment0Pages;
+ IVT_ENTRY *Int0x10;
+ EFI_STATUS Status;
+ UINTN Pam1Address;
+ UINT8 Pam1;
+ UINTN SegmentCPages;
+ VBE_INFO *VbeInfoFull;
+ VBE_INFO_BASE *VbeInfo;
+ UINT8 *Ptr;
+ UINTN Printed;
+ VBE_MODE_INFO *VbeModeInfo;
+ UINTN i;
+
+ Segment0 = 0x00000;
+ SegmentC = 0xC0000;
+ SegmentF = 0xF0000;
+
+ //
+ // Attempt to cover the real mode IVT with an allocation. This is a UEFI
+ // driver, hence the arch protocols have been installed previously. Among
+ // those, the CPU arch protocol has configured the IDT, so we can overwrite
+ // the IVT used in real mode.
+ //
+ // The allocation request may fail, eg. if LegacyBiosDxe has already run.
+ //
+ Segment0Pages = 1;
+ Int0x10 = (IVT_ENTRY *)(UINTN)Segment0 + 0x10;
+ Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode,
+ Segment0Pages, &Segment0);
+
+ if (EFI_ERROR (Status)) {
+ EFI_PHYSICAL_ADDRESS Handler;
+
+ //
+ // Check if a video BIOS handler has been installed previously -- we
+ // shouldn't override a real video BIOS with our shim, nor our own shim if
+ // it's already present.
+ //
+ Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
+ if (Handler >= SegmentC && Handler < SegmentF) {
+ DEBUG ((DEBUG_VERBOSE, "%a: Video BIOS handler found at %04x:%04x\n",
+ __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+ return;
+ }
+
+ //
+ // Otherwise we'll overwrite the Int10h vector, even though we may not own
+ // the page at zero.
+ //
+ DEBUG ((DEBUG_VERBOSE, "%a: failed to allocate page at zero: %r\n",
+ __FUNCTION__, Status));
+ } else {
+ //
+ // We managed to allocate the page at zero. SVN r14218 guarantees that it
+ // is NUL-filled.
+ //
+ ASSERT (Int0x10->Segment == 0x0000);
+ ASSERT (Int0x10->Offset == 0x0000);
+ }
+
+ //
+ // Put the shim in place first.
+ //
+ Pam1Address = PCI_LIB_ADDRESS (0, 0, 0, 0x5A);
+ //
+ // low nibble covers 0xC0000 to 0xC3FFF
+ // high nibble covers 0xC4000 to 0xC7FFF
+ // bit1 in each nibble is Write Enable
+ // bit0 in each nibble is Read Enable
+ //
+ Pam1 = PciRead8 (Pam1Address);
+ PciWrite8 (Pam1Address, Pam1 | (BIT1 | BIT0));
+
+ //
+ // We never added memory space durig PEI or DXE for the C segment, so we
+ // don't need to (and can't) allocate from there. Also, guest operating
+ // systems will see a hole in the UEFI memory map there.
+ //
+ SegmentCPages = 4;
+
+ ASSERT (sizeof gVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
+ CopyMem ((VOID *)(UINTN)SegmentC, gVbeShim, sizeof gVbeShim);
+
+ //
+ // Fill in the VBE INFO structure.
+ //
+ VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
+ VbeInfo = &VbeInfoFull->Base;
+ Ptr = VbeInfoFull->Buffer;
+
+ CopyMem (VbeInfo->Signature, "VESA", 4);
+ VbeInfo->VesaVersion = 0x0200;
+
+ VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, "FBSD", 5);
+ Ptr += 5;
+
+ VbeInfo->Capabilities = BIT1 | BIT0; // DAC can be switched into 8-bit mode
+
+ VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ for (i = 0; i < NUM_VBE_MODES; i ++) {
+ *(UINT16*)Ptr = vbeModeIds[i]; // mode number
+ Ptr += 2;
+ }
+ *(UINT16*)Ptr = 0xFFFF; // mode list terminator
+ Ptr += 2;
+
+ VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
+ VbeInfo->OemSoftwareVersion = 0x0200;
+
+ VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, "FBSD", 5);
+ Ptr += 5;
+
+ VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ Printed = AsciiSPrint ((CHAR8 *)Ptr,
+ sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s",
+ CardName);
+ Ptr += Printed + 1;
+
+ VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
+ Ptr += sizeof mProductRevision;
+
+ ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
+ ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
+
+ //
+ // Fill in the VBE MODE INFO structure list
+ //
+ VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
+ Ptr = (UINT8 *)VbeModeInfo;
+ for (i = 0; i < NUM_VBE_MODES; i++) {
+ vbeModes[i].LfbAddress = (UINT32)FrameBufferBase;
+ CopyMem (Ptr, &vbeModes[i], 0x32);
+ Ptr += 0x32;
+ }
+
+ ZeroMem (Ptr, 56); // Clear remaining bytes
+
+ //
+ // Clear Write Enable (bit1), keep Read Enable (bit0) set
+ //
+ PciWrite8 (Pam1Address, (Pam1 & ~BIT1) | BIT0);
+
+ //
+ // Second, point the Int10h vector at the shim.
+ //
+ Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
+ Int0x10->Offset = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
+
+ DEBUG ((DEBUG_INFO, "%a: VBE shim installed to %x:%x\n",
+ __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.h b/OvmfPkg/IntelGvtGopDxe/VbeShim.h
new file mode 100644
index 000000000000..601b1465cbe5
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.h
@@ -0,0 +1,912 @@
+//
+// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
+//
+#ifndef _VBE_SHIM_H_
+#define _VBE_SHIM_H_
+STATIC CONST UINT8 gVbeShim[] = {
+ /* 00000000 nop */ 0x90,
+ /* 00000001 nop */ 0x90,
+ /* 00000002 nop */ 0x90,
+ /* 00000003 nop */ 0x90,
+ /* 00000004 nop */ 0x90,
+ /* 00000005 nop */ 0x90,
+ /* 00000006 nop */ 0x90,
+ /* 00000007 nop */ 0x90,
+ /* 00000008 nop */ 0x90,
+ /* 00000009 nop */ 0x90,
+ /* 0000000A nop */ 0x90,
+ /* 0000000B nop */ 0x90,
+ /* 0000000C nop */ 0x90,
+ /* 0000000D nop */ 0x90,
+ /* 0000000E nop */ 0x90,
+ /* 0000000F nop */ 0x90,
+ /* 00000010 nop */ 0x90,
+ /* 00000011 nop */ 0x90,
+ /* 00000012 nop */ 0x90,
+ /* 00000013 nop */ 0x90,
+ /* 00000014 nop */ 0x90,
+ /* 00000015 nop */ 0x90,
+ /* 00000016 nop */ 0x90,
+ /* 00000017 nop */ 0x90,
+ /* 00000018 nop */ 0x90,
+ /* 00000019 nop */ 0x90,
+ /* 0000001A nop */ 0x90,
+ /* 0000001B nop */ 0x90,
+ /* 0000001C nop */ 0x90,
+ /* 0000001D nop */ 0x90,
+ /* 0000001E nop */ 0x90,
+ /* 0000001F nop */ 0x90,
+ /* 00000020 nop */ 0x90,
+ /* 00000021 nop */ 0x90,
+ /* 00000022 nop */ 0x90,
+ /* 00000023 nop */ 0x90,
+ /* 00000024 nop */ 0x90,
+ /* 00000025 nop */ 0x90,
+ /* 00000026 nop */ 0x90,
+ /* 00000027 nop */ 0x90,
+ /* 00000028 nop */ 0x90,
+ /* 00000029 nop */ 0x90,
+ /* 0000002A nop */ 0x90,
+ /* 0000002B nop */ 0x90,
+ /* 0000002C nop */ 0x90,
+ /* 0000002D nop */ 0x90,
+ /* 0000002E nop */ 0x90,
+ /* 0000002F nop */ 0x90,
+ /* 00000030 nop */ 0x90,
+ /* 00000031 nop */ 0x90,
+ /* 00000032 nop */ 0x90,
+ /* 00000033 nop */ 0x90,
+ /* 00000034 nop */ 0x90,
+ /* 00000035 nop */ 0x90,
+ /* 00000036 nop */ 0x90,
+ /* 00000037 nop */ 0x90,
+ /* 00000038 nop */ 0x90,
+ /* 00000039 nop */ 0x90,
+ /* 0000003A nop */ 0x90,
+ /* 0000003B nop */ 0x90,
+ /* 0000003C nop */ 0x90,
+ /* 0000003D nop */ 0x90,
+ /* 0000003E nop */ 0x90,
+ /* 0000003F nop */ 0x90,
+ /* 00000040 nop */ 0x90,
+ /* 00000041 nop */ 0x90,
+ /* 00000042 nop */ 0x90,
+ /* 00000043 nop */ 0x90,
+ /* 00000044 nop */ 0x90,
+ /* 00000045 nop */ 0x90,
+ /* 00000046 nop */ 0x90,
+ /* 00000047 nop */ 0x90,
+ /* 00000048 nop */ 0x90,
+ /* 00000049 nop */ 0x90,
+ /* 0000004A nop */ 0x90,
+ /* 0000004B nop */ 0x90,
+ /* 0000004C nop */ 0x90,
+ /* 0000004D nop */ 0x90,
+ /* 0000004E nop */ 0x90,
+ /* 0000004F nop */ 0x90,
+ /* 00000050 nop */ 0x90,
+ /* 00000051 nop */ 0x90,
+ /* 00000052 nop */ 0x90,
+ /* 00000053 nop */ 0x90,
+ /* 00000054 nop */ 0x90,
+ /* 00000055 nop */ 0x90,
+ /* 00000056 nop */ 0x90,
+ /* 00000057 nop */ 0x90,
+ /* 00000058 nop */ 0x90,
+ /* 00000059 nop */ 0x90,
+ /* 0000005A nop */ 0x90,
+ /* 0000005B nop */ 0x90,
+ /* 0000005C nop */ 0x90,
+ /* 0000005D nop */ 0x90,
+ /* 0000005E nop */ 0x90,
+ /* 0000005F nop */ 0x90,
+ /* 00000060 nop */ 0x90,
+ /* 00000061 nop */ 0x90,
+ /* 00000062 nop */ 0x90,
+ /* 00000063 nop */ 0x90,
+ /* 00000064 nop */ 0x90,
+ /* 00000065 nop */ 0x90,
+ /* 00000066 nop */ 0x90,
+ /* 00000067 nop */ 0x90,
+ /* 00000068 nop */ 0x90,
+ /* 00000069 nop */ 0x90,
+ /* 0000006A nop */ 0x90,
+ /* 0000006B nop */ 0x90,
+ /* 0000006C nop */ 0x90,
+ /* 0000006D nop */ 0x90,
+ /* 0000006E nop */ 0x90,
+ /* 0000006F nop */ 0x90,
+ /* 00000070 nop */ 0x90,
+ /* 00000071 nop */ 0x90,
+ /* 00000072 nop */ 0x90,
+ /* 00000073 nop */ 0x90,
+ /* 00000074 nop */ 0x90,
+ /* 00000075 nop */ 0x90,
+ /* 00000076 nop */ 0x90,
+ /* 00000077 nop */ 0x90,
+ /* 00000078 nop */ 0x90,
+ /* 00000079 nop */ 0x90,
+ /* 0000007A nop */ 0x90,
+ /* 0000007B nop */ 0x90,
+ /* 0000007C nop */ 0x90,
+ /* 0000007D nop */ 0x90,
+ /* 0000007E nop */ 0x90,
+ /* 0000007F nop */ 0x90,
+ /* 00000080 nop */ 0x90,
+ /* 00000081 nop */ 0x90,
+ /* 00000082 nop */ 0x90,
+ /* 00000083 nop */ 0x90,
+ /* 00000084 nop */ 0x90,
+ /* 00000085 nop */ 0x90,
+ /* 00000086 nop */ 0x90,
+ /* 00000087 nop */ 0x90,
+ /* 00000088 nop */ 0x90,
+ /* 00000089 nop */ 0x90,
+ /* 0000008A nop */ 0x90,
+ /* 0000008B nop */ 0x90,
+ /* 0000008C nop */ 0x90,
+ /* 0000008D nop */ 0x90,
+ /* 0000008E nop */ 0x90,
+ /* 0000008F nop */ 0x90,
+ /* 00000090 nop */ 0x90,
+ /* 00000091 nop */ 0x90,
+ /* 00000092 nop */ 0x90,
+ /* 00000093 nop */ 0x90,
+ /* 00000094 nop */ 0x90,
+ /* 00000095 nop */ 0x90,
+ /* 00000096 nop */ 0x90,
+ /* 00000097 nop */ 0x90,
+ /* 00000098 nop */ 0x90,
+ /* 00000099 nop */ 0x90,
+ /* 0000009A nop */ 0x90,
+ /* 0000009B nop */ 0x90,
+ /* 0000009C nop */ 0x90,
+ /* 0000009D nop */ 0x90,
+ /* 0000009E nop */ 0x90,
+ /* 0000009F nop */ 0x90,
+ /* 000000A0 nop */ 0x90,
+ /* 000000A1 nop */ 0x90,
+ /* 000000A2 nop */ 0x90,
+ /* 000000A3 nop */ 0x90,
+ /* 000000A4 nop */ 0x90,
+ /* 000000A5 nop */ 0x90,
+ /* 000000A6 nop */ 0x90,
+ /* 000000A7 nop */ 0x90,
+ /* 000000A8 nop */ 0x90,
+ /* 000000A9 nop */ 0x90,
+ /* 000000AA nop */ 0x90,
+ /* 000000AB nop */ 0x90,
+ /* 000000AC nop */ 0x90,
+ /* 000000AD nop */ 0x90,
+ /* 000000AE nop */ 0x90,
+ /* 000000AF nop */ 0x90,
+ /* 000000B0 nop */ 0x90,
+ /* 000000B1 nop */ 0x90,
+ /* 000000B2 nop */ 0x90,
+ /* 000000B3 nop */ 0x90,
+ /* 000000B4 nop */ 0x90,
+ /* 000000B5 nop */ 0x90,
+ /* 000000B6 nop */ 0x90,
+ /* 000000B7 nop */ 0x90,
+ /* 000000B8 nop */ 0x90,
+ /* 000000B9 nop */ 0x90,
+ /* 000000BA nop */ 0x90,
+ /* 000000BB nop */ 0x90,
+ /* 000000BC nop */ 0x90,
+ /* 000000BD nop */ 0x90,
+ /* 000000BE nop */ 0x90,
+ /* 000000BF nop */ 0x90,
+ /* 000000C0 nop */ 0x90,
+ /* 000000C1 nop */ 0x90,
+ /* 000000C2 nop */ 0x90,
+ /* 000000C3 nop */ 0x90,
+ /* 000000C4 nop */ 0x90,
+ /* 000000C5 nop */ 0x90,
+ /* 000000C6 nop */ 0x90,
+ /* 000000C7 nop */ 0x90,
+ /* 000000C8 nop */ 0x90,
+ /* 000000C9 nop */ 0x90,
+ /* 000000CA nop */ 0x90,
+ /* 000000CB nop */ 0x90,
+ /* 000000CC nop */ 0x90,
+ /* 000000CD nop */ 0x90,
+ /* 000000CE nop */ 0x90,
+ /* 000000CF nop */ 0x90,
+ /* 000000D0 nop */ 0x90,
+ /* 000000D1 nop */ 0x90,
+ /* 000000D2 nop */ 0x90,
+ /* 000000D3 nop */ 0x90,
+ /* 000000D4 nop */ 0x90,
+ /* 000000D5 nop */ 0x90,
+ /* 000000D6 nop */ 0x90,
+ /* 000000D7 nop */ 0x90,
+ /* 000000D8 nop */ 0x90,
+ /* 000000D9 nop */ 0x90,
+ /* 000000DA nop */ 0x90,
+ /* 000000DB nop */ 0x90,
+ /* 000000DC nop */ 0x90,
+ /* 000000DD nop */ 0x90,
+ /* 000000DE nop */ 0x90,
+ /* 000000DF nop */ 0x90,
+ /* 000000E0 nop */ 0x90,
+ /* 000000E1 nop */ 0x90,
+ /* 000000E2 nop */ 0x90,
+ /* 000000E3 nop */ 0x90,
+ /* 000000E4 nop */ 0x90,
+ /* 000000E5 nop */ 0x90,
+ /* 000000E6 nop */ 0x90,
+ /* 000000E7 nop */ 0x90,
+ /* 000000E8 nop */ 0x90,
+ /* 000000E9 nop */ 0x90,
+ /* 000000EA nop */ 0x90,
+ /* 000000EB nop */ 0x90,
+ /* 000000EC nop */ 0x90,
+ /* 000000ED nop */ 0x90,
+ /* 000000EE nop */ 0x90,
+ /* 000000EF nop */ 0x90,
+ /* 000000F0 nop */ 0x90,
+ /* 000000F1 nop */ 0x90,
+ /* 000000F2 nop */ 0x90,
+ /* 000000F3 nop */ 0x90,
+ /* 000000F4 nop */ 0x90,
+ /* 000000F5 nop */ 0x90,
+ /* 000000F6 nop */ 0x90,
+ /* 000000F7 nop */ 0x90,
+ /* 000000F8 nop */ 0x90,
+ /* 000000F9 nop */ 0x90,
+ /* 000000FA nop */ 0x90,
+ /* 000000FB nop */ 0x90,
+ /* 000000FC nop */ 0x90,
+ /* 000000FD nop */ 0x90,
+ /* 000000FE nop */ 0x90,
+ /* 000000FF nop */ 0x90,
+ /* 00000100 nop */ 0x90,
+ /* 00000101 nop */ 0x90,
+ /* 00000102 nop */ 0x90,
+ /* 00000103 nop */ 0x90,
+ /* 00000104 nop */ 0x90,
+ /* 00000105 nop */ 0x90,
+ /* 00000106 nop */ 0x90,
+ /* 00000107 nop */ 0x90,
+ /* 00000108 nop */ 0x90,
+ /* 00000109 nop */ 0x90,
+ /* 0000010A nop */ 0x90,
+ /* 0000010B nop */ 0x90,
+ /* 0000010C nop */ 0x90,
+ /* 0000010D nop */ 0x90,
+ /* 0000010E nop */ 0x90,
+ /* 0000010F nop */ 0x90,
+ /* 00000110 nop */ 0x90,
+ /* 00000111 nop */ 0x90,
+ /* 00000112 nop */ 0x90,
+ /* 00000113 nop */ 0x90,
+ /* 00000114 nop */ 0x90,
+ /* 00000115 nop */ 0x90,
+ /* 00000116 nop */ 0x90,
+ /* 00000117 nop */ 0x90,
+ /* 00000118 nop */ 0x90,
+ /* 00000119 nop */ 0x90,
+ /* 0000011A nop */ 0x90,
+ /* 0000011B nop */ 0x90,
+ /* 0000011C nop */ 0x90,
+ /* 0000011D nop */ 0x90,
+ /* 0000011E nop */ 0x90,
+ /* 0000011F nop */ 0x90,
+ /* 00000120 nop */ 0x90,
+ /* 00000121 nop */ 0x90,
+ /* 00000122 nop */ 0x90,
+ /* 00000123 nop */ 0x90,
+ /* 00000124 nop */ 0x90,
+ /* 00000125 nop */ 0x90,
+ /* 00000126 nop */ 0x90,
+ /* 00000127 nop */ 0x90,
+ /* 00000128 nop */ 0x90,
+ /* 00000129 nop */ 0x90,
+ /* 0000012A nop */ 0x90,
+ /* 0000012B nop */ 0x90,
+ /* 0000012C nop */ 0x90,
+ /* 0000012D nop */ 0x90,
+ /* 0000012E nop */ 0x90,
+ /* 0000012F nop */ 0x90,
+ /* 00000130 nop */ 0x90,
+ /* 00000131 nop */ 0x90,
+ /* 00000132 nop */ 0x90,
+ /* 00000133 nop */ 0x90,
+ /* 00000134 nop */ 0x90,
+ /* 00000135 nop */ 0x90,
+ /* 00000136 nop */ 0x90,
+ /* 00000137 nop */ 0x90,
+ /* 00000138 nop */ 0x90,
+ /* 00000139 nop */ 0x90,
+ /* 0000013A nop */ 0x90,
+ /* 0000013B nop */ 0x90,
+ /* 0000013C nop */ 0x90,
+ /* 0000013D nop */ 0x90,
+ /* 0000013E nop */ 0x90,
+ /* 0000013F nop */ 0x90,
+ /* 00000140 nop */ 0x90,
+ /* 00000141 nop */ 0x90,
+ /* 00000142 nop */ 0x90,
+ /* 00000143 nop */ 0x90,
+ /* 00000144 nop */ 0x90,
+ /* 00000145 nop */ 0x90,
+ /* 00000146 nop */ 0x90,
+ /* 00000147 nop */ 0x90,
+ /* 00000148 nop */ 0x90,
+ /* 00000149 nop */ 0x90,
+ /* 0000014A nop */ 0x90,
+ /* 0000014B nop */ 0x90,
+ /* 0000014C nop */ 0x90,
+ /* 0000014D nop */ 0x90,
+ /* 0000014E nop */ 0x90,
+ /* 0000014F nop */ 0x90,
+ /* 00000150 nop */ 0x90,
+ /* 00000151 nop */ 0x90,
+ /* 00000152 nop */ 0x90,
+ /* 00000153 nop */ 0x90,
+ /* 00000154 nop */ 0x90,
+ /* 00000155 nop */ 0x90,
+ /* 00000156 nop */ 0x90,
+ /* 00000157 nop */ 0x90,
+ /* 00000158 nop */ 0x90,
+ /* 00000159 nop */ 0x90,
+ /* 0000015A nop */ 0x90,
+ /* 0000015B nop */ 0x90,
+ /* 0000015C nop */ 0x90,
+ /* 0000015D nop */ 0x90,
+ /* 0000015E nop */ 0x90,
+ /* 0000015F nop */ 0x90,
+ /* 00000160 nop */ 0x90,
+ /* 00000161 nop */ 0x90,
+ /* 00000162 nop */ 0x90,
+ /* 00000163 nop */ 0x90,
+ /* 00000164 nop */ 0x90,
+ /* 00000165 nop */ 0x90,
+ /* 00000166 nop */ 0x90,
+ /* 00000167 nop */ 0x90,
+ /* 00000168 nop */ 0x90,
+ /* 00000169 nop */ 0x90,
+ /* 0000016A nop */ 0x90,
+ /* 0000016B nop */ 0x90,
+ /* 0000016C nop */ 0x90,
+ /* 0000016D nop */ 0x90,
+ /* 0000016E nop */ 0x90,
+ /* 0000016F nop */ 0x90,
+ /* 00000170 nop */ 0x90,
+ /* 00000171 nop */ 0x90,
+ /* 00000172 nop */ 0x90,
+ /* 00000173 nop */ 0x90,
+ /* 00000174 nop */ 0x90,
+ /* 00000175 nop */ 0x90,
+ /* 00000176 nop */ 0x90,
+ /* 00000177 nop */ 0x90,
+ /* 00000178 nop */ 0x90,
+ /* 00000179 nop */ 0x90,
+ /* 0000017A nop */ 0x90,
+ /* 0000017B nop */ 0x90,
+ /* 0000017C nop */ 0x90,
+ /* 0000017D nop */ 0x90,
+ /* 0000017E nop */ 0x90,
+ /* 0000017F nop */ 0x90,
+ /* 00000180 nop */ 0x90,
+ /* 00000181 nop */ 0x90,
+ /* 00000182 nop */ 0x90,
+ /* 00000183 nop */ 0x90,
+ /* 00000184 nop */ 0x90,
+ /* 00000185 nop */ 0x90,
+ /* 00000186 nop */ 0x90,
+ /* 00000187 nop */ 0x90,
+ /* 00000188 nop */ 0x90,
+ /* 00000189 nop */ 0x90,
+ /* 0000018A nop */ 0x90,
+ /* 0000018B nop */ 0x90,
+ /* 0000018C nop */ 0x90,
+ /* 0000018D nop */ 0x90,
+ /* 0000018E nop */ 0x90,
+ /* 0000018F nop */ 0x90,
+ /* 00000190 nop */ 0x90,
+ /* 00000191 nop */ 0x90,
+ /* 00000192 nop */ 0x90,
+ /* 00000193 nop */ 0x90,
+ /* 00000194 nop */ 0x90,
+ /* 00000195 nop */ 0x90,
+ /* 00000196 nop */ 0x90,
+ /* 00000197 nop */ 0x90,
+ /* 00000198 nop */ 0x90,
+ /* 00000199 nop */ 0x90,
+ /* 0000019A nop */ 0x90,
+ /* 0000019B nop */ 0x90,
+ /* 0000019C nop */ 0x90,
+ /* 0000019D nop */ 0x90,
+ /* 0000019E nop */ 0x90,
+ /* 0000019F nop */ 0x90,
+ /* 000001A0 nop */ 0x90,
+ /* 000001A1 nop */ 0x90,
+ /* 000001A2 nop */ 0x90,
+ /* 000001A3 nop */ 0x90,
+ /* 000001A4 nop */ 0x90,
+ /* 000001A5 nop */ 0x90,
+ /* 000001A6 nop */ 0x90,
+ /* 000001A7 nop */ 0x90,
+ /* 000001A8 nop */ 0x90,
+ /* 000001A9 nop */ 0x90,
+ /* 000001AA nop */ 0x90,
+ /* 000001AB nop */ 0x90,
+ /* 000001AC nop */ 0x90,
+ /* 000001AD nop */ 0x90,
+ /* 000001AE nop */ 0x90,
+ /* 000001AF nop */ 0x90,
+ /* 000001B0 nop */ 0x90,
+ /* 000001B1 nop */ 0x90,
+ /* 000001B2 nop */ 0x90,
+ /* 000001B3 nop */ 0x90,
+ /* 000001B4 nop */ 0x90,
+ /* 000001B5 nop */ 0x90,
+ /* 000001B6 nop */ 0x90,
+ /* 000001B7 nop */ 0x90,
+ /* 000001B8 nop */ 0x90,
+ /* 000001B9 nop */ 0x90,
+ /* 000001BA nop */ 0x90,
+ /* 000001BB nop */ 0x90,
+ /* 000001BC nop */ 0x90,
+ /* 000001BD nop */ 0x90,
+ /* 000001BE nop */ 0x90,
+ /* 000001BF nop */ 0x90,
+ /* 000001C0 nop */ 0x90,
+ /* 000001C1 nop */ 0x90,
+ /* 000001C2 nop */ 0x90,
+ /* 000001C3 nop */ 0x90,
+ /* 000001C4 nop */ 0x90,
+ /* 000001C5 nop */ 0x90,
+ /* 000001C6 nop */ 0x90,
+ /* 000001C7 nop */ 0x90,
+ /* 000001C8 nop */ 0x90,
+ /* 000001C9 nop */ 0x90,
+ /* 000001CA nop */ 0x90,
+ /* 000001CB nop */ 0x90,
+ /* 000001CC nop */ 0x90,
+ /* 000001CD nop */ 0x90,
+ /* 000001CE nop */ 0x90,
+ /* 000001CF nop */ 0x90,
+ /* 000001D0 nop */ 0x90,
+ /* 000001D1 nop */ 0x90,
+ /* 000001D2 nop */ 0x90,
+ /* 000001D3 nop */ 0x90,
+ /* 000001D4 nop */ 0x90,
+ /* 000001D5 nop */ 0x90,
+ /* 000001D6 nop */ 0x90,
+ /* 000001D7 nop */ 0x90,
+ /* 000001D8 nop */ 0x90,
+ /* 000001D9 nop */ 0x90,
+ /* 000001DA nop */ 0x90,
+ /* 000001DB nop */ 0x90,
+ /* 000001DC nop */ 0x90,
+ /* 000001DD nop */ 0x90,
+ /* 000001DE nop */ 0x90,
+ /* 000001DF nop */ 0x90,
+ /* 000001E0 nop */ 0x90,
+ /* 000001E1 nop */ 0x90,
+ /* 000001E2 nop */ 0x90,
+ /* 000001E3 nop */ 0x90,
+ /* 000001E4 nop */ 0x90,
+ /* 000001E5 nop */ 0x90,
+ /* 000001E6 nop */ 0x90,
+ /* 000001E7 nop */ 0x90,
+ /* 000001E8 nop */ 0x90,
+ /* 000001E9 nop */ 0x90,
+ /* 000001EA nop */ 0x90,
+ /* 000001EB nop */ 0x90,
+ /* 000001EC nop */ 0x90,
+ /* 000001ED nop */ 0x90,
+ /* 000001EE nop */ 0x90,
+ /* 000001EF nop */ 0x90,
+ /* 000001F0 nop */ 0x90,
+ /* 000001F1 nop */ 0x90,
+ /* 000001F2 nop */ 0x90,
+ /* 000001F3 nop */ 0x90,
+ /* 000001F4 nop */ 0x90,
+ /* 000001F5 nop */ 0x90,
+ /* 000001F6 nop */ 0x90,
+ /* 000001F7 nop */ 0x90,
+ /* 000001F8 nop */ 0x90,
+ /* 000001F9 nop */ 0x90,
+ /* 000001FA nop */ 0x90,
+ /* 000001FB nop */ 0x90,
+ /* 000001FC nop */ 0x90,
+ /* 000001FD nop */ 0x90,
+ /* 000001FE nop */ 0x90,
+ /* 000001FF nop */ 0x90,
+ /* 00000200 cmp ax,0x4f00 */ 0x3D, 0x00, 0x4F,
+ /* 00000203 jz 0x237 */ 0x74, 0x32,
+ /* 00000205 cmp ax,0x4f01 */ 0x3D, 0x01, 0x4F,
+ /* 00000208 jz 0x257 */ 0x74, 0x4D,
+ /* 0000020A cmp ax,0x4f02 */ 0x3D, 0x02, 0x4F,
+ /* 0000020D jz near 0x2c8 */ 0x0F, 0x84, 0xB7, 0x00,
+ /* 00000211 cmp ax,0x4f03 */ 0x3D, 0x03, 0x4F,
+ /* 00000214 jz near 0x325 */ 0x0F, 0x84, 0x0D, 0x01,
+ /* 00000218 cmp ax,0x4f10 */ 0x3D, 0x10, 0x4F,
+ /* 0000021B jz near 0x337 */ 0x0F, 0x84, 0x18, 0x01,
+ /* 0000021F cmp ax,0x4f15 */ 0x3D, 0x15, 0x4F,
+ /* 00000222 jz near 0x344 */ 0x0F, 0x84, 0x1E, 0x01,
+ /* 00000226 cmp ah,0x0 */ 0x80, 0xFC, 0x00,
+ /* 00000229 jz near 0x363 */ 0x0F, 0x84, 0x36, 0x01,
+ /* 0000022D push si */ 0x56,
+ /* 0000022E mov si,0x3d7 */ 0xBE, 0xD7, 0x03,
+ /* 00000231 call 0x3ad */ 0xE8, 0x79, 0x01,
+ /* 00000234 pop si */ 0x5E,
+ /* 00000235 jmp short 0x235 */ 0xEB, 0xFE,
+ /* 00000237 push es */ 0x06,
+ /* 00000238 push di */ 0x57,
+ /* 00000239 push ds */ 0x1E,
+ /* 0000023A push si */ 0x56,
+ /* 0000023B push cx */ 0x51,
+ /* 0000023C push si */ 0x56,
+ /* 0000023D mov si,0x3eb */ 0xBE, 0xEB, 0x03,
+ /* 00000240 call 0x3ad */ 0xE8, 0x6A, 0x01,
+ /* 00000243 pop si */ 0x5E,
+ /* 00000244 push cs */ 0x0E,
+ /* 00000245 pop ds */ 0x1F,
+ /* 00000246 mov si,0x0 */ 0xBE, 0x00, 0x00,
+ /* 00000249 mov cx,0x100 */ 0xB9, 0x00, 0x01,
+ /* 0000024C cld */ 0xFC,
+ /* 0000024D rep movsb */ 0xF3, 0xA4,
+ /* 0000024F pop cx */ 0x59,
+ /* 00000250 pop si */ 0x5E,
+ /* 00000251 pop ds */ 0x1F,
+ /* 00000252 pop di */ 0x5F,
+ /* 00000253 pop es */ 0x07,
+ /* 00000254 jmp 0x395 */ 0xE9, 0x3E, 0x01,
+ /* 00000257 push es */ 0x06,
+ /* 00000258 push di */ 0x57,
+ /* 00000259 push ds */ 0x1E,
+ /* 0000025A push si */ 0x56,
+ /* 0000025B push cx */ 0x51,
+ /* 0000025C push si */ 0x56,
+ /* 0000025D mov si,0x3f6 */ 0xBE, 0xF6, 0x03,
+ /* 00000260 call 0x3ad */ 0xE8, 0x4A, 0x01,
+ /* 00000263 pop si */ 0x5E,
+ /* 00000264 and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
+ /* 00000268 cmp cx,0x13f */ 0x81, 0xF9, 0x3F, 0x01,
+ /* 0000026C jz 0x284 */ 0x74, 0x16,
+ /* 0000026E cmp cx,0x140 */ 0x81, 0xF9, 0x40, 0x01,
+ /* 00000272 jz 0x291 */ 0x74, 0x1D,
+ /* 00000274 cmp cx,0x141 */ 0x81, 0xF9, 0x41, 0x01,
+ /* 00000278 jz 0x29e */ 0x74, 0x24,
+ /* 0000027A push si */ 0x56,
+ /* 0000027B mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 0000027E call 0x3ad */ 0xE8, 0x2C, 0x01,
+ /* 00000281 pop si */ 0x5E,
+ /* 00000282 jmp short 0x235 */ 0xEB, 0xB1,
+ /* 00000284 push si */ 0x56,
+ /* 00000285 mov si,0x46b */ 0xBE, 0x6B, 0x04,
+ /* 00000288 call 0x3ad */ 0xE8, 0x22, 0x01,
+ /* 0000028B pop si */ 0x5E,
+ /* 0000028C mov si,0x100 */ 0xBE, 0x00, 0x01,
+ /* 0000028F jmp short 0x2b8 */ 0xEB, 0x27,
+ /* 00000291 push si */ 0x56,
+ /* 00000292 mov si,0x47d */ 0xBE, 0x7D, 0x04,
+ /* 00000295 call 0x3ad */ 0xE8, 0x15, 0x01,
+ /* 00000298 pop si */ 0x5E,
+ /* 00000299 mov si,0x132 */ 0xBE, 0x32, 0x01,
+ /* 0000029C jmp short 0x2b8 */ 0xEB, 0x1A,
+ /* 0000029E push si */ 0x56,
+ /* 0000029F mov si,0x48f */ 0xBE, 0x8F, 0x04,
+ /* 000002A2 call 0x3ad */ 0xE8, 0x08, 0x01,
+ /* 000002A5 pop si */ 0x5E,
+ /* 000002A6 mov si,0x164 */ 0xBE, 0x64, 0x01,
+ /* 000002A9 jmp short 0x2b8 */ 0xEB, 0x0D,
+ /* 000002AB push si */ 0x56,
+ /* 000002AC mov si,0x4a2 */ 0xBE, 0xA2, 0x04,
+ /* 000002AF call 0x3ad */ 0xE8, 0xFB, 0x00,
+ /* 000002B2 pop si */ 0x5E,
+ /* 000002B3 mov si,0x196 */ 0xBE, 0x96, 0x01,
+ /* 000002B6 jmp short 0x2b8 */ 0xEB, 0x00,
+ /* 000002B8 push cs */ 0x0E,
+ /* 000002B9 pop ds */ 0x1F,
+ /* 000002BA mov cx,0x32 */ 0xB9, 0x32, 0x00,
+ /* 000002BD cld */ 0xFC,
+ /* 000002BE rep movsb */ 0xF3, 0xA4,
+ /* 000002C0 pop cx */ 0x59,
+ /* 000002C1 pop si */ 0x5E,
+ /* 000002C2 pop ds */ 0x1F,
+ /* 000002C3 pop di */ 0x5F,
+ /* 000002C4 pop es */ 0x07,
+ /* 000002C5 jmp 0x395 */ 0xE9, 0xCD, 0x00,
+ /* 000002C8 push dx */ 0x52,
+ /* 000002C9 push ax */ 0x50,
+ /* 000002CA push si */ 0x56,
+ /* 000002CB mov si,0x410 */ 0xBE, 0x10, 0x04,
+ /* 000002CE call 0x3ad */ 0xE8, 0xDC, 0x00,
+ /* 000002D1 pop si */ 0x5E,
+ /* 000002D2 and bx,0xbfff */ 0x81, 0xE3, 0xFF, 0xBF,
+ /* 000002D6 cmp bx,0x13f */ 0x81, 0xFB, 0x3F, 0x01,
+ /* 000002DA jz 0x2f3 */ 0x74, 0x17,
+ /* 000002DC cmp bx,0x140 */ 0x81, 0xFB, 0x40, 0x01,
+ /* 000002E0 jz 0x2fd */ 0x74, 0x1B,
+ /* 000002E2 cmp bx,0x141 */ 0x81, 0xFB, 0x41, 0x01,
+ /* 000002E6 jz 0x307 */ 0x74, 0x1F,
+ /* 000002E8 push si */ 0x56,
+ /* 000002E9 mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 000002EC call 0x3ad */ 0xE8, 0xBE, 0x00,
+ /* 000002EF pop si */ 0x5E,
+ /* 000002F0 jmp 0x235 */ 0xE9, 0x42, 0xFF,
+ /* 000002F3 push si */ 0x56,
+ /* 000002F4 mov si,0x46b */ 0xBE, 0x6B, 0x04,
+ /* 000002F7 call 0x3ad */ 0xE8, 0xB3, 0x00,
+ /* 000002FA pop si */ 0x5E,
+ /* 000002FB jmp short 0x319 */ 0xEB, 0x1C,
+ /* 000002FD push si */ 0x56,
+ /* 000002FE mov si,0x47d */ 0xBE, 0x7D, 0x04,
+ /* 00000301 call 0x3ad */ 0xE8, 0xA9, 0x00,
+ /* 00000304 pop si */ 0x5E,
+ /* 00000305 jmp short 0x319 */ 0xEB, 0x12,
+ /* 00000307 push si */ 0x56,
+ /* 00000308 mov si,0x48f */ 0xBE, 0x8F, 0x04,
+ /* 0000030B call 0x3ad */ 0xE8, 0x9F, 0x00,
+ /* 0000030E pop si */ 0x5E,
+ /* 0000030F jmp short 0x319 */ 0xEB, 0x08,
+ /* 00000311 push si */ 0x56,
+ /* 00000312 mov si,0x4a2 */ 0xBE, 0xA2, 0x04,
+ /* 00000315 call 0x3ad */ 0xE8, 0x95, 0x00,
+ /* 00000318 pop si */ 0x5E,
+ /* 00000319 mov [0x4b0],bl */ 0x88, 0x1E, 0xB0, 0x04,
+ /* 0000031D mov [0x4b1],bh */ 0x88, 0x3E, 0xB1, 0x04,
+ /* 00000321 pop ax */ 0x58,
+ /* 00000322 pop dx */ 0x5A,
+ /* 00000323 jmp short 0x395 */ 0xEB, 0x70,
+ /* 00000325 push si */ 0x56,
+ /* 00000326 mov si,0x405 */ 0xBE, 0x05, 0x04,
+ /* 00000329 call 0x3ad */ 0xE8, 0x81, 0x00,
+ /* 0000032C pop si */ 0x5E,
+ /* 0000032D mov bl,[0x4b0] */ 0x8A, 0x1E, 0xB0, 0x04,
+ /* 00000331 mov bh,[0x4b1] */ 0x8A, 0x3E, 0xB1, 0x04,
+ /* 00000335 jmp short 0x395 */ 0xEB, 0x5E,
+ /* 00000337 push si */ 0x56,
+ /* 00000338 mov si,0x43b */ 0xBE, 0x3B, 0x04,
+ /* 0000033B call 0x3ad */ 0xE8, 0x6F, 0x00,
+ /* 0000033E pop si */ 0x5E,
+ /* 0000033F mov bx,0x80 */ 0xBB, 0x80, 0x00,
+ /* 00000342 jmp short 0x395 */ 0xEB, 0x51,
+ /* 00000344 push es */ 0x06,
+ /* 00000345 push di */ 0x57,
+ /* 00000346 push ds */ 0x1E,
+ /* 00000347 push si */ 0x56,
+ /* 00000348 push cx */ 0x51,
+ /* 00000349 push si */ 0x56,
+ /* 0000034A mov si,0x450 */ 0xBE, 0x50, 0x04,
+ /* 0000034D call 0x3ad */ 0xE8, 0x5D, 0x00,
+ /* 00000350 pop si */ 0x5E,
+ /* 00000351 push cs */ 0x0E,
+ /* 00000352 pop ds */ 0x1F,
+ /* 00000353 mov si,0x4b2 */ 0xBE, 0xB2, 0x04,
+ /* 00000356 mov cx,0x80 */ 0xB9, 0x80, 0x00,
+ /* 00000359 cld */ 0xFC,
+ /* 0000035A rep movsb */ 0xF3, 0xA4,
+ /* 0000035C pop cx */ 0x59,
+ /* 0000035D pop si */ 0x5E,
+ /* 0000035E pop ds */ 0x1F,
+ /* 0000035F pop di */ 0x5F,
+ /* 00000360 pop es */ 0x07,
+ /* 00000361 jmp short 0x395 */ 0xEB, 0x32,
+ /* 00000363 push si */ 0x56,
+ /* 00000364 mov si,0x41b */ 0xBE, 0x1B, 0x04,
+ /* 00000367 call 0x3ad */ 0xE8, 0x43, 0x00,
+ /* 0000036A pop si */ 0x5E,
+ /* 0000036B cmp al,0x3 */ 0x3C, 0x03,
+ /* 0000036D jz 0x37e */ 0x74, 0x0F,
+ /* 0000036F cmp al,0x12 */ 0x3C, 0x12,
+ /* 00000371 jz 0x38a */ 0x74, 0x17,
+ /* 00000373 push si */ 0x56,
+ /* 00000374 mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 00000377 call 0x3ad */ 0xE8, 0x33, 0x00,
+ /* 0000037A pop si */ 0x5E,
+ /* 0000037B jmp 0x235 */ 0xE9, 0xB7, 0xFE,
+ /* 0000037E push si */ 0x56,
+ /* 0000037F mov si,0x45c */ 0xBE, 0x5C, 0x04,
+ /* 00000382 call 0x3ad */ 0xE8, 0x28, 0x00,
+ /* 00000385 pop si */ 0x5E,
+ /* 00000386 mov al,0x0 */ 0xB0, 0x00,
+ /* 00000388 jmp short 0x38c */ 0xEB, 0x02,
+ /* 0000038A mov al,0x0 */ 0xB0, 0x00,
+ /* 0000038C push si */ 0x56,
+ /* 0000038D mov si,0x3c2 */ 0xBE, 0xC2, 0x03,
+ /* 00000390 call 0x3ad */ 0xE8, 0x1A, 0x00,
+ /* 00000393 pop si */ 0x5E,
+ /* 00000394 iret */ 0xCF,
+ /* 00000395 push si */ 0x56,
+ /* 00000396 mov si,0x3c2 */ 0xBE, 0xC2, 0x03,
+ /* 00000399 call 0x3ad */ 0xE8, 0x11, 0x00,
+ /* 0000039C pop si */ 0x5E,
+ /* 0000039D mov ax,0x4f */ 0xB8, 0x4F, 0x00,
+ /* 000003A0 iret */ 0xCF,
+ /* 000003A1 push si */ 0x56,
+ /* 000003A2 mov si,0x3c8 */ 0xBE, 0xC8, 0x03,
+ /* 000003A5 call 0x3ad */ 0xE8, 0x05, 0x00,
+ /* 000003A8 pop si */ 0x5E,
+ /* 000003A9 mov ax,0x24f */ 0xB8, 0x4F, 0x02,
+ /* 000003AC iret */ 0xCF,
+ /* 000003AD pusha */ 0x60,
+ /* 000003AE push ds */ 0x1E,
+ /* 000003AF push cs */ 0x0E,
+ /* 000003B0 pop ds */ 0x1F,
+ /* 000003B1 mov dx,0x220 */ 0xBA, 0x20, 0x02,
+ /* 000003B4 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+ /* 000003B7 lodsb */ 0xAC,
+ /* 000003B8 cmp al,0x0 */ 0x3C, 0x00,
+ /* 000003BA jz 0x3bf */ 0x74, 0x03,
+ /* 000003BC out dx,al */ 0xEE,
+ /* 000003BD jmp short 0x3b7 */ 0xEB, 0xF8,
+ /* 000003BF pop ds */ 0x1F,
+ /* 000003C0 popa */ 0x61,
+ /* 000003C1 ret */ 0xC3,
+ /* 000003C2 jna 0x413 */ 0x76, 0x4F,
+ /* 000003C4 imul cx,[di],byte +0xa */ 0x6B, 0x0D, 0x0A,
+ /* 000003C7 add [bp+0x55],dh */ 0x00, 0x76, 0x55,
+ /* 000003CA outsb */ 0x6E,
+ /* 000003CB jnc 0x442 */ 0x73, 0x75,
+ /* 000003CD jo 0x43f */ 0x70, 0x70,
+ /* 000003CF outsw */ 0x6F,
+ /* 000003D0 jc 0x446 */ 0x72, 0x74,
+ /* 000003D2 fs or ax,0xa */ 0x65, 0x64, 0x0D, 0x0A, 0x00,
+ /* 000003D7 jna 0x42e */ 0x76, 0x55,
+ /* 000003D9 outsb */ 0x6E,
+ /* 000003DA imul bp,[bp+0x6f],byte +0x77 */ 0x6B, 0x6E, 0x6F, 0x77,
+ /* 000003DE outsb */ 0x6E,
+ /* 000003DF and [bp+0x75],al */ 0x20, 0x46, 0x75,
+ /* 000003E2 outsb */ 0x6E,
+ /* 000003E3 arpl [si+0x69],si */ 0x63, 0x74, 0x69,
+ /* 000003E6 outsw */ 0x6F,
+ /* 000003E7 outsb */ 0x6E,
+ /* 000003E8 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 000003EB jna 0x434 */ 0x76, 0x47,
+ /* 000003ED gs jz 0x439 */ 0x65, 0x74, 0x49,
+ /* 000003F0 outsb */ 0x6E,
+ /* 000003F1 outsd */ 0x66, 0x6F,
+ /* 000003F3 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 000003F6 jna 0x43f */ 0x76, 0x47,
+ /* 000003F8 gs jz 0x448 */ 0x65, 0x74, 0x4D,
+ /* 000003FB outsw */ 0x6F,
+ /* 000003FC gs dec cx */ 0x64, 0x65, 0x49,
+ /* 000003FF outsb */ 0x6E,
+ /* 00000400 outsd */ 0x66, 0x6F,
+ /* 00000402 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 00000405 jna 0x44e */ 0x76, 0x47,
+ /* 00000407 gs jz 0x457 */ 0x65, 0x74, 0x4D,
+ /* 0000040A outsw */ 0x6F,
+ /* 0000040B gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 00000410 jna 0x465 */ 0x76, 0x53,
+ /* 00000412 gs jz 0x462 */ 0x65, 0x74, 0x4D,
+ /* 00000415 outsw */ 0x6F,
+ /* 00000416 gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 0000041B jna 0x470 */ 0x76, 0x53,
+ /* 0000041D gs jz 0x46d */ 0x65, 0x74, 0x4D,
+ /* 00000420 outsw */ 0x6F,
+ /* 00000421 gs dec sp */ 0x64, 0x65, 0x4C,
+ /* 00000424 gs a32 popa */ 0x65, 0x67, 0x61,
+ /* 00000427 arpl [bx+di+0xd],di */ 0x63, 0x79, 0x0D,
+ /* 0000042A or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000042C jna 0x483 */ 0x76, 0x55,
+ /* 0000042E outsb */ 0x6E,
+ /* 0000042F imul bp,[bx+0x77],byte +0x6e */ 0x6B, 0x6F, 0x77, 0x6E,
+ /* 00000433 and [di+0x6f],cl */ 0x20, 0x4D, 0x6F,
+ /* 00000436 gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 0000043B jna 0x484 */ 0x76, 0x47,
+ /* 0000043D gs jz 0x490 */ 0x65, 0x74, 0x50,
+ /* 00000440 insw */ 0x6D,
+ /* 00000441 inc bx */ 0x43,
+ /* 00000442 popa */ 0x61,
+ /* 00000443 jo 0x4a6 */ 0x70, 0x61,
+ /* 00000445 bound bp,[bx+di+0x6c] */ 0x62, 0x69, 0x6C,
+ /* 00000448 imul si,[si+0x69],word 0x7365 */ 0x69, 0x74, 0x69, 0x65, 0x73,
+ /* 0000044D or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 00000450 jna 0x4a4 */ 0x76, 0x52,
+ /* 00000452 gs popa */ 0x65, 0x61,
+ /* 00000454 fs inc bp */ 0x64, 0x45,
+ /* 00000456 imul sp,[fs:si+0xd],word 0xa */ 0x64, 0x69, 0x64, 0x0D, 0x0A, 0x00,
+ /* 0000045C jna 0x4aa */ 0x76, 0x4C,
+ /* 0000045E gs a32 popa */ 0x65, 0x67, 0x61,
+ /* 00000461 arpl [bx+di+0x4d],di */ 0x63, 0x79, 0x4D,
+ /* 00000464 outsw */ 0x6F,
+ /* 00000465 xor cx,[gs:di] */ 0x64, 0x65, 0x33, 0x0D,
+ /* 00000469 or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000046B insw */ 0x6D,
+ /* 0000046C outsw */ 0x6F,
+ /* 0000046D gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000470 ss xor al,0x30 */ 0x36, 0x34, 0x30,
+ /* 00000473 js 0x4a9 */ 0x78, 0x34,
+ /* 00000475 cmp [bx+si],dh */ 0x38, 0x30,
+ /* 00000477 js 0x4ac */ 0x78, 0x33,
+ /* 00000479 xor cl,[di] */ 0x32, 0x0D,
+ /* 0000047B or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000047D insw */ 0x6D,
+ /* 0000047E outsw */ 0x6F,
+ /* 0000047F gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000482 cmp [bx+si],dh */ 0x38, 0x30,
+ /* 00000484 xor [bx+si+0x36],bh */ 0x30, 0x78, 0x36,
+ /* 00000487 xor [bx+si],dh */ 0x30, 0x30,
+ /* 00000489 js 0x4be */ 0x78, 0x33,
+ /* 0000048B xor cl,[di] */ 0x32, 0x0D,
+ /* 0000048D or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000048F insw */ 0x6D,
+ /* 00000490 outsw */ 0x6F,
+ /* 00000491 gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000494 xor [bx+si],si */ 0x31, 0x30,
+ /* 00000496 xor dh,[si] */ 0x32, 0x34,
+ /* 00000498 js 0x4d1 */ 0x78, 0x37,
+ /* 0000049A cmp [ss:bx+si+0x33],bh */ 0x36, 0x38, 0x78, 0x33,
+ /* 0000049E xor cl,[di] */ 0x32, 0x0D,
+ /* 000004A0 or al,[bx+si] */ 0x0A, 0x00,
+ /* 000004A2 insw */ 0x6D,
+ /* 000004A3 outsw */ 0x6F,
+ /* 000004A4 gs pop di */ 0x64, 0x65, 0x5F,
+ /* 000004A7 jnz 0x517 */ 0x75, 0x6E,
+ /* 000004A9 jnz 0x51e */ 0x75, 0x73,
+ /* 000004AB fs or ax,0xa */ 0x65, 0x64, 0x0D, 0x0A, 0x00,
+ /* 000004B0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004BA add [bx+si],al */ 0x00, 0x00,
+ /* 000004BC add [bx+si],al */ 0x00, 0x00,
+ /* 000004BE add [bx+si],al */ 0x00, 0x00,
+ /* 000004C0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004CA add [bx+si],al */ 0x00, 0x00,
+ /* 000004CC add [bx+si],al */ 0x00, 0x00,
+ /* 000004CE add [bx+si],al */ 0x00, 0x00,
+ /* 000004D0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004DA add [bx+si],al */ 0x00, 0x00,
+ /* 000004DC add [bx+si],al */ 0x00, 0x00,
+ /* 000004DE add [bx+si],al */ 0x00, 0x00,
+ /* 000004E0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004EA add [bx+si],al */ 0x00, 0x00,
+ /* 000004EC add [bx+si],al */ 0x00, 0x00,
+ /* 000004EE add [bx+si],al */ 0x00, 0x00,
+ /* 000004F0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004FA add [bx+si],al */ 0x00, 0x00,
+ /* 000004FC add [bx+si],al */ 0x00, 0x00,
+ /* 000004FE add [bx+si],al */ 0x00, 0x00,
+ /* 00000500 add [bx+si],al */ 0x00, 0x00,
+ /* 00000502 add [bx+si],al */ 0x00, 0x00,
+ /* 00000504 add [bx+si],al */ 0x00, 0x00,
+ /* 00000506 add [bx+si],al */ 0x00, 0x00,
+ /* 00000508 add [bx+si],al */ 0x00, 0x00,
+ /* 0000050A add [bx+si],al */ 0x00, 0x00,
+ /* 0000050C add [bx+si],al */ 0x00, 0x00,
+ /* 0000050E add [bx+si],al */ 0x00, 0x00,
+ /* 00000510 add [bx+si],al */ 0x00, 0x00,
+ /* 00000512 add [bx+si],al */ 0x00, 0x00,
+ /* 00000514 add [bx+si],al */ 0x00, 0x00,
+ /* 00000516 add [bx+si],al */ 0x00, 0x00,
+ /* 00000518 add [bx+si],al */ 0x00, 0x00,
+ /* 0000051A add [bx+si],al */ 0x00, 0x00,
+ /* 0000051C add [bx+si],al */ 0x00, 0x00,
+ /* 0000051E add [bx+si],al */ 0x00, 0x00,
+ /* 00000520 add [bx+si],al */ 0x00, 0x00,
+ /* 00000522 add [bx+si],al */ 0x00, 0x00,
+ /* 00000524 add [bx+si],al */ 0x00, 0x00,
+ /* 00000526 add [bx+si],al */ 0x00, 0x00,
+ /* 00000528 add [bx+si],al */ 0x00, 0x00,
+ /* 0000052A add [bx+si],al */ 0x00, 0x00,
+ /* 0000052C add [bx+si],al */ 0x00, 0x00,
+ /* 0000052E add [bx+si],al */ 0x00, 0x00,
+ /* 00000530 add [bx+si],al */ 0x00, 0x00,
+ /* 00000532 add [bx+si],al */ 0x00, 0x00,
+};
+#endif
diff --git a/OvmfPkg/IntelGvtGopDxe/VbeShim.sh b/OvmfPkg/IntelGvtGopDxe/VbeShim.sh
new file mode 100755
index 000000000000..4f61e5220b01
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VbeShim.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+###
+# @file
+# Shell script to assemble and dump the fake Int10h handler from NASM source to
+# a C array.
+#
+# Copyright (C) 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+set -e -u
+
+STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
+
+#
+# Install exit handler -- remove temporary files.
+#
+exit_handler()
+{
+ rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
+ "$STEM".bytes
+}
+trap exit_handler EXIT
+
+#
+# Assemble the source file.
+#
+nasm -o "$STEM".bin "$STEM".asm
+
+#
+# Disassemble it, in order to get a binary dump associated with the source.
+# (ndisasm doesn't recognize the "--" end-of-options delimiter.)
+#
+ndisasm "$STEM".bin >"$STEM".disasm
+
+#
+# Create three files, each with one column of the disassembly.
+#
+# The first column contains the offsets, and it starts the comment.
+#
+cut -c 1-8 -- "$STEM".disasm \
+| sed -e 's,^, /* ,' >"$STEM".offsets
+
+#
+# The second column contains the assembly-language instructions, and it closes
+# the comment. We first pad it to 30 characters.
+#
+cut -c 29- -- "$STEM".disasm \
+| sed -e 's,$, ,' \
+ -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
+
+#
+# The third column contains the bytes corresponding to the instruction,
+# represented as C integer constants. First strip trailing whitespace from the
+# middle column of the input disassembly, then process pairs of nibbles.
+#
+cut -c 11-28 -- "$STEM".disasm \
+| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' | sed 's/0x ,//g' >"$STEM".bytes
+
+#
+# Write the output file, recombining the columns. The output should have CRLF
+# line endings.
+#
+{
+ printf '//\n'
+ printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
+ "$(basename -- "$0")"
+ printf '//\n'
+ printf '#ifndef _VBE_SHIM_H_\n'
+ printf '#define _VBE_SHIM_H_\n'
+ printf 'STATIC CONST UINT8 gVbeShim[] = {\n'
+ paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
+ printf '};\n'
+ printf '#endif\n'
+} \
+| unix2dos >"$STEM".h
diff --git a/OvmfPkg/IntelGvtGopDxe/VirtualGpu.c b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.c
new file mode 100644
index 000000000000..dc2c23706c8b
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.c
@@ -0,0 +1,400 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Common.h"
+#include "VirtualGpu.h"
+#include "GpuReg.h"
+#include "Gtt.h"
+#include "Display.h"
+#include <Library/QemuFwCfgLib.h>
+
+EFI_STATUS
+IntelVirtualGpuActive (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ PCI_TYPE00 PciHdr = {0};
+ UINT64 Magic = 0;
+ UINT32 Version = 0;
+ UINT16 VerMajor = 0, VerMinor = 0;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (PciHdr) / sizeof (UINT32),
+ &PciHdr
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read PCI config header, status %d\n", Status
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ if (!IS_PCI_DISPLAY (&PciHdr) || PciHdr.Hdr.VendorId != 0x8086) {
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "Skip non Intel PCI Display [%04x:%04x] class:%x\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, PciHdr.Hdr.ClassCode[2]
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BAR_IDX0,
+ vgtif_reg(magic),
+ 1,
+ &Magic
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read GVT magic from [%04x:%04x], status %d\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, Status
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ if (Magic != VGT_MAGIC) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Read magic from [%04x:%04x], get %x expect %x\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, Magic, VGT_MAGIC
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ vgtif_reg(version_major),
+ 1,
+ &Version
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read GVT version from [%04x:%04x], status %d\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, Status
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ VerMajor = Version & 0xFFFF;
+ VerMinor = (Version & 0xFFFF) >> 16;
+ if (VerMajor < VGT_VERSION_MAJOR) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Check VGT interface version of [%04x:%04x], got %x.%x, expect %x.*\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId,
+ VerMajor, VerMinor, VGT_VERSION_MAJOR
+ );
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ GVT_DEBUG (EFI_D_INFO,
+ "Intel GVT-g virtual GPU [%04x:%04x] detected, version %x.%x\n",
+ PciHdr.Hdr.VendorId, PciHdr.Hdr.DeviceId, VerMajor, VerMinor
+ );
+ Status = EFI_SUCCESS;
+
+Done:
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ UINT8 Val8;
+ UINT64 Val64;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ PciIo = Private->PciIo;
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_VENDOR_ID_OFFSET,
+ 1,
+ &VirtualGpu->VendorId
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read PCI_VENDOR_ID_OFFSET, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_DEVICE_ID_OFFSET,
+ 1,
+ &VirtualGpu->DeviceId
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't read PCI_DEVICE_ID_OFFSET, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ PCI_BASE_ADDRESSREG_OFFSET + PCI_BAR_IDX2 * 4,
+ 1,
+ &Val64
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Can't get GMADR from BAR2, status %d\n", Status);
+ goto Done;
+ }
+
+ if (Val64 & 0x1) {
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR, "BAR2 isn't memory space, status %d\n", Status);
+ goto Done;
+ }
+
+ switch (Val64 >> 1 & 0x3) {
+ case 0:
+ VirtualGpu->GpuMemAddr = Val64 & 0xFFFFFFF0;
+ GVT_DEBUG (EFI_D_VERBOSE, "BAR2 has 32-bit access space\n");
+ break;
+ case 2:
+ VirtualGpu->GpuMemAddr = Val64 & ~0xF;
+ GVT_DEBUG (EFI_D_VERBOSE, "BAR2 has 64-bit access space\n");
+ break;
+ default:
+ Status = EFI_OUT_OF_RESOURCES;
+ GVT_DEBUG (EFI_D_ERROR,
+ "BAR2 has unknown access space, status %d\n", Status
+ );
+ goto Done;
+ break;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_REG_MSAC,
+ 1,
+ &Val8
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Can't get MSAC from %x, status %d\n", PCI_REG_MSAC, Status
+ );
+ goto Done;
+ }
+
+ Val8 &= 0x1F;
+ if (Val8 & 0x10) {
+ VirtualGpu->GpuMemSizeM = 4096;
+ } else {
+ Val8 &= 0xF;
+ if (Val8 & 0x8) {
+ VirtualGpu->GpuMemSizeM = 2048;
+ } else {
+ Val8 &= 0x7;
+ if (Val8 & 0x4) {
+ VirtualGpu->GpuMemSizeM = 1024;
+ } else {
+ Val8 &= 0x3;
+ if (Val8 & 0x2) {
+ VirtualGpu->GpuMemSizeM = 512;
+ } else {
+ if (Val8 & 0x1) {
+ VirtualGpu->GpuMemSizeM = 256;
+ } else {
+ VirtualGpu->GpuMemSizeM = 128;
+ }
+ }
+ }
+ }
+ }
+
+ Status = QemuFwCfgFindFile ("etc/igd-opregion", &FwCfgItem, &FwCfgSize);
(1) This feature still relies on "etc/igd-opregion".

And so, while this driver "poses" as a UEFI_DRIVER module for a PCI
device, it remains a platform driver.

That's still a deal-breaker -- please refer to
<https://bugzilla.tianocore.org/show_bug.cgi?id=935>, specifically
comment 15.

Has there been any improvement regarding the requirement that the
opregion come from QEMU via fw_cfg, for the Windows guest driver's sake?

(I really wish you had first asked about this feature, before authoring
a driver with 4000+ lines!)
Sorry for the confusion. Yes I understand the history in the case of IGD passthrough. Maybe it's better if I've added an RFC in the subject. I'm not intended to sell the patch directly, instead to have a patch first so that have more details to receive valuable comments. Either UEFI_DRIVER or platform driver should follow OVMF requirement for sure, there is no doubt for that.
The current igd-opregion indeed block us finding better solution to get rid of it due to the dependency of guest driver implementation. So for this part there is nothing can do but follow the driver behavior.

However there is still use case to boot a UEFI guest with only one GPU (Intel GVT-g vGPU) but there is no screen output duing non-OS stage, this is the exact problem this patch tries to resolve.

Unlike the patch you mentioned, the majority of this patch consists of two parts: GOP and mdev device emulation. I thought feedback on them are still valuable, thus sent out as a single patch first.

(2) If the fw_cfg file in question is not found, the patch simply
ignores it. We log a debug message about it (not even an error message),
but then proceed with the rest of the code as if everything was OK.

Is that intentional?
It's absolutely OK doing in this way. etc/igd-opregion is indeed not clear for OVMF. Assume future guest driver decouple itself with igd-opregion, which some guest driver doesn't rely on it already, the intention of this patch is to have a common solution for Intel GVT-g vGPU.

Again the intention is not push the patch into EDK2, but RFC and find out accepable part into upstream, either EDK2 or EDK2-platform. Sorry for not making it clear at first time.


(3) There's a whole lot of style issues in the code, and I absolutely
don't see myself identifying every single one of those for you, in a
4000+ line driver.

(EFI_D_xxx macro usage, line wrapping issues with multi-line function
calls, comment style problems, an assumption of varargs support with
function-like macros on all edk2 toolchains, building the driver only
for X64, ...)
Style issues are mainly due to I looked all around EDK2 and found different components have very different styles so just follow what I saw. I'll review them again and make sure there are fixed. I'll also double check and make sure all other compling toolchains won't be broken.
It'll be great if you cound suggest a good-style reference so that I can strictly follow it.


I'd much prefer if you maintained this driver outside of OvmfPkg
(perhaps somewhere in edk2-platforms, possibly under
Drivers/OptionRomPkg/), and then, given a UEFI driver binary, you passed
it to QEMU via the device's ROM BAR, per
<https://bugzilla.tianocore.org/show_bug.cgi?id=935#c17>.

This is acceptable. In device pass through case, UEFI driver passed as ROM BAR are commonly used so it can meet the using scenario.

I'd be *somewhat* open to accepting this driver into OvmfPkg if:

- you formally assume on-going reviewership for the driver
(Maintainers.txt),
Since it's tight to Intel GVT-g, I'll discuss with GVT-g maintainer and keep a on-going reviewship in the list so that it can be actively mainained as GVT-g.
- you set the feature test macro in the DSC files to FALSE by default,
Consider it done. It won't be a problem.
- you fix all the style issues with the help of other Intel contributors,
I'll revise and update.
- you explicitly document somewhere that the fw_cfg access is a design
bug in a UEFI driver (especially for an assigned device) -- it remains a
platform driver, contrary to the semblance, for the sake of the arguably
broken Windows guest driver,
Sure.
- you make the driver 32-bit clean and include it in the IA32 and
IA32X64 DSC files too.
Sure.

I won't even mention how unreviewable a "patch bomb" like this is; such
a driver should be constructed (erected) gradually over 10-20 patches at
the minimum, isolating the UEFI driver model code from the device
initialization from the various GOP member functions. I won't mention
that because I don't intend to review this driver in depth anyway.
Not be a problem. I'll find a way to split the patch to a reviewable series.

I might be willing to accept it as an optional (disabled by default)
"code dump", as long as you ensure the bare minimum of edk2 style and
build requirements, and take full responsibility for the driver in the
future.
... Honestly, the fact that you never asked about this feature on any
edk2 list, and that you (apparently) never searched the TianoCore
bugzilla tracker for potentially related BZs (such as #935), doesn't
really boost my confidence in this feature.
It's my negligence. I do realized the existence of #935, which is always referenced in some down-upstream project. The situation here is we have a user experience problem at first and need resolve it asap so the off-tree
patch is crafted first. Then we are looking for re-using the implemenation in up-stream so that it can benefits more open source users. Since the draft patch is done, it feels like reasonly to send to community as an opening so that experts can direclty suggest an acceptable way to re-use some of the implmentation to craft an upstream version. igd-opregion is a dirty part but is not the foundation or dependency of this GOP driver.


In summary if my understanding is correct, this driver is closer to a platform driver (due to it's dependecy to vfio) than a full simulated device driver. Maybe there is tiny chance it can be accepted in OvmfPkg, but Drivers/OptionRomPkg is the more proper place it should sit.

I'll send the revised version to Drivers/OptionRomPkg with all review comments (now & future) considered. igd-opregion maybe completely removed from the driver, or could be kept in code but disabled by default, the reason and explanation will be documented somewhere in case some very specific sceaniro requires.


"There's always a first step in everything". Please accept my apollogy if this first step had an impact on the technical discussion. As developer I payed more attention to the implemenation and re-usability, but could lack big picture thinking and overall considerations. Thus your and other maintainers' comments are very valuable to drive to the right direction.

Laszlo

+ if (Status == EFI_SUCCESS && FwCfgSize == OPREGION_SIZE) {
+ // OpRegion must sit below 4 GB
+ VirtualGpu->OpRegion = SIZE_4GB - 1;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE),
+ &VirtualGpu->OpRegion
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to allocate %d pages size %lx for OpRegion, status %d\n",
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE), OPREGION_SIZE, Status
+ );
+ goto Done;
+ }
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (FwCfgSize, (VOID*)VirtualGpu->OpRegion);
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_REG_ASLS,
+ 1,
+ (UINT32*)&VirtualGpu->OpRegion
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to write OpRegion %p to PCI config offset 0x%x, status %d\n",
+ VirtualGpu->OpRegion, PCI_REG_ASLS, Status
+ );
+ goto Done;
+ } else {
+ GVT_DEBUG (EFI_D_INFO,
+ "OpRegion %p is set to PCI config offset 0x%x\n",
+ VirtualGpu->OpRegion, PCI_REG_ASLS
+ );
+ }
+ } else {
+ GVT_DEBUG (EFI_D_VERBOSE,
+ "Not igd-opregion found in QEMU firmware config\n"
+ );
+ }
+
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.mappable_gmadr.base), &VirtualGpu->VisibleOffset);
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.mappable_gmadr.size), &VirtualGpu->VisibleSize);
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.nonmappable_gmadr.base), &VirtualGpu->InvisibleOffset);
+ RegRead32 (Private,
+ vgtif_reg(avail_rs.nonmappable_gmadr.size), &VirtualGpu->InvisibleSize);
+ VirtualGpu->VisibleGGTTOffset = VirtualGpu->VisibleOffset >> GTT_PAGE_SHIFT;
+ VirtualGpu->VisibleGGTTSize = VirtualGpu->VisibleSize >> GTT_PAGE_SHIFT;
+ VirtualGpu->InvisibleGGTTOffset = VirtualGpu->InvisibleOffset >> GTT_PAGE_SHIFT;
+ VirtualGpu->InvisibleGGTTSize = VirtualGpu->InvisibleSize >> GTT_PAGE_SHIFT;
+
+ GVT_DEBUG (
+ EFI_D_INFO,
+ "GMADR [0x%lx - 0x%lx], size %d MB\n",
+ VirtualGpu->GpuMemAddr,
+ VirtualGpu->GpuMemAddr + VirtualGpu->GpuMemSizeM * 0x100000,
+ VirtualGpu->GpuMemSizeM
+ );
+ GVT_DEBUG (
+ EFI_D_INFO,
+ "visible offset [0x%x - 0x%x] size %d KB, GGTT range [%x - %x]\n",
+ VirtualGpu->VisibleOffset,
+ VirtualGpu->VisibleOffset + VirtualGpu->VisibleSize,
+ VirtualGpu->VisibleSize / 0x400,
+ VirtualGpu->VisibleGGTTOffset,
+ VirtualGpu->VisibleGGTTOffset + VirtualGpu->VisibleGGTTSize
+ );
+ GVT_DEBUG (
+ EFI_D_INFO,
+ "invisible offset [0x%x - 0x%x] size %d KB, GGTT range [%x - %x]\n",
+ VirtualGpu->InvisibleOffset,
+ VirtualGpu->InvisibleOffset + VirtualGpu->InvisibleSize,
+ VirtualGpu->InvisibleSize / 0x400,
+ VirtualGpu->InvisibleGGTTOffset,
+ VirtualGpu->InvisibleGGTTOffset + VirtualGpu->InvisibleGGTTSize
+ );
+
+ Status = IntelVirtualGpuDisplayInit (Private);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to initialize display, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = IntelVirtualGpuSetMode (&Private->GraphicsOutputProtocol, 0);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to set init display mode, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ Status = IntelVirtualGpuNotifyDisplayReady (Private, TRUE);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "Fail to notify display ready, status %d\n", Status
+ );
+ goto Done;
+ }
+
+ // Flush all reg after DisplayReady
+ Status = IntelVirtualGpuEnableDisplay (
+ Private,
+ 0,
+ TRUE
+ );
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
+
+EFI_STATUS
+IntelVirtualGpuClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ PINTEL_VIRTUAL_GPU VirtualGpu;
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: >>>\n", __FUNCTION__);
+
+ Status = IntelVirtualGpuDisplayClean (Private);
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR, "Fail to clean display, status %d\n", Status);
+ goto Done;
+ }
+
+ VirtualGpu = (PINTEL_VIRTUAL_GPU)Private->VirtualGpu;
+ if (VirtualGpu->OpRegion) {
+ Status = gBS->FreePages (
+ VirtualGpu->OpRegion,
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE)
+ );
+ if (EFI_ERROR (Status)) {
+ GVT_DEBUG (EFI_D_ERROR,
+ "FreePages failed for OpRegion, pages %d, size %d, status %d\n",
+ EFI_SIZE_TO_PAGES (OPREGION_SIZE), OPREGION_SIZE, Status
+ );
+ goto Done;
+ }
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+
+ GVT_DEBUG (EFI_D_VERBOSE, "%a: <<<\n", __FUNCTION__);
+
+ return Status;
+}
diff --git a/OvmfPkg/IntelGvtGopDxe/VirtualGpu.h b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.h
new file mode 100644
index 000000000000..60d80eadb3ac
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/VirtualGpu.h
@@ -0,0 +1,52 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __VIRTUALGPU_H_
+#define __VIRTUALGPU_H_
+
+#include <Display.h>
+
+#define PCI_REG_MSAC 0x62
+#define PCI_REG_ASLS 0xFC
+
+#define OPREGION_SIZE SIZE_8KB
+
+typedef struct _INTEL_VIRTUAL_GPU {
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ EFI_PHYSICAL_ADDRESS OpRegion;
+ EFI_PHYSICAL_ADDRESS GpuMemAddr;
+ UINT32 GpuMemSizeM;
+ UINT32 VisibleOffset;
+ UINT32 VisibleSize;
+ UINT32 VisibleGGTTOffset;
+ UINT32 VisibleGGTTSize;
+ UINT32 InvisibleOffset;
+ UINT32 InvisibleSize;
+ UINT32 InvisibleGGTTOffset;
+ UINT32 InvisibleGGTTSize;
+ INTEL_VIRTUAL_GPU_DISPLAY Display;
+} INTEL_VIRTUAL_GPU, *PINTEL_VIRTUAL_GPU;
+
+EFI_STATUS
+IntelVirtualGpuActive (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ );
+
+EFI_STATUS
+IntelVirtualGpuInit (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+IntelVirtualGpuClean (
+ IN OUT GVT_GOP_PRIVATE_DATA *Private
+ );
+
+#endif //__VIRTUALGPU_H_





Rebecca Cran
 

On 3/5/2021 6:19 AM, Laszlo Ersek wrote:

(3) There's a whole lot of style issues in the code, and I absolutely
don't see myself identifying every single one of those for you, in a
4000+ line driver.

(EFI_D_xxx macro usage, line wrapping issues with multi-line function
calls, comment style problems, an assumption of varargs support with
function-like macros on all edk2 toolchains, building the driver only
for X64, ...)
The other style issue I noticed was the leading double underscores in the include guards - e.g.:

diff --git a/OvmfPkg/IntelGvtGopDxe/Common.h b/OvmfPkg/IntelGvtGopDxe/Common.h
new file mode 100644
index 000000000000..cf30752eb8f3
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Common.h
@@ -0,0 +1,45 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __COMMON_H_

--
Rebecca Cran


Colin Xu
 

On Fri, 12 Mar 2021, Rebecca Cran wrote:

On 3/5/2021 6:19 AM, Laszlo Ersek wrote:

(3) There's a whole lot of style issues in the code, and I absolutely
don't see myself identifying every single one of those for you, in a
4000+ line driver.
(EFI_D_xxx macro usage, line wrapping issues with multi-line function
calls, comment style problems, an assumption of varargs support with
function-like macros on all edk2 toolchains, building the driver only
for X64, ...)
The other style issue I noticed was the leading double underscores in the include guards - e.g.:
Thanks Rebecca. I'll fix them.

Best Regards,
Colin

diff --git a/OvmfPkg/IntelGvtGopDxe/Common.h b/OvmfPkg/IntelGvtGopDxe/Common.h
new file mode 100644
index 000000000000..cf30752eb8f3
--- /dev/null
+++ b/OvmfPkg/IntelGvtGopDxe/Common.h
@@ -0,0 +1,45 @@
+/** @file
+ Component name for the QEMU video controller.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __COMMON_H_

--
Rebecca Cran







Gerd Hoffmann <kraxel@...>
 

Hi,

Thanks a lot for your comment, Laszlo! See my reply also end of the patch.
Hi Gerd, Alex, would you mind share your thoughts as well?
(2) If the fw_cfg file in question is not found, the patch simply
ignores it. We log a debug message about it (not even an error message),
but then proceed with the rest of the code as if everything was OK.

Is that intentional?
It's absolutely OK doing in this way. etc/igd-opregion is indeed not clear
for OVMF. Assume future guest driver decouple itself with igd-opregion,
which some guest driver doesn't rely on it already, the intention of this
patch is to have a common solution for Intel GVT-g vGPU.
For reference, on seabios the opregion workflow looks like this:

(1) i915 gvt kernel driver generates opregion content.
(2) opregion is exported as special vfio region.
(3) qemu copies over the content to etc/igd-opregion fw_cfg file.
(4) seabios loads etc/igd-opregion, stores it in ram, writes the
address to a register.
(5) guest os driver reads the register to find the opregion.

So, first question is how dynamic is the opregion content?

On physical hardware it clearly is, it carries information on how
outputs are wired to physical DVI / HDMI / DP plugs and for laptops how
to drive the lvds panel built in. For virtual hardware this is fixed
and a simple "all outputs are displayport".

What else is in there? Anything which might need changes when the gvt
driver is updated? Given that some guest drivers do not depend on the
opregion I assume this is not the case.

So I'm wondering whenever there is a good reason in the first place to
generate the opregion in the i915 gvt kernel driver. Is it an option to
generate the opregion in this IntelGvtGopDxe driver instead? That would
clearly be the easiest solution.

Failing that we should at least take fw_cfg out of the loop. It is just
a middle man here and not needed at all. As discussed before the pci
rom bar can do the job instead. That will remove any platform
dependencies from the driver, it only need to talk to the device itself
then.

take care,
Gerd


Colin Xu
 

On Fri, 12 Mar 2021, Gerd Hoffmann wrote:

Hi,

Thanks a lot for your comment, Laszlo! See my reply also end of the patch.
Hi Gerd, Alex, would you mind share your thoughts as well?
(2) If the fw_cfg file in question is not found, the patch simply
ignores it. We log a debug message about it (not even an error message),
but then proceed with the rest of the code as if everything was OK.

Is that intentional?
It's absolutely OK doing in this way. etc/igd-opregion is indeed not clear
for OVMF. Assume future guest driver decouple itself with igd-opregion,
which some guest driver doesn't rely on it already, the intention of this
patch is to have a common solution for Intel GVT-g vGPU.
For reference, on seabios the opregion workflow looks like this:

(1) i915 gvt kernel driver generates opregion content.
(2) opregion is exported as special vfio region.
(3) qemu copies over the content to etc/igd-opregion fw_cfg file.
(4) seabios loads etc/igd-opregion, stores it in ram, writes the
address to a register.
(5) guest os driver reads the register to find the opregion.

So, first question is how dynamic is the opregion content?

On physical hardware it clearly is, it carries information on how
outputs are wired to physical DVI / HDMI / DP plugs and for laptops how
to drive the lvds panel built in. For virtual hardware this is fixed
and a simple "all outputs are displayport".

What else is in there? Anything which might need changes when the gvt
driver is updated? Given that some guest drivers do not depend on the
opregion I assume this is not the case.

So I'm wondering whenever there is a good reason in the first place to
generate the opregion in the i915 gvt kernel driver. Is it an option to
generate the opregion in this IntelGvtGopDxe driver instead? That would
clearly be the easiest solution.
It's absolutely true that generating opregion in IntelGvtGopDxe could be an option. I thought the reason that i915/gvt generating the opregion is due to the design that how to emulate a GPU in a layered hierarchy. On physical hardware, OpRegion is part of firmware, loaded and comsumed by GPU SW stack. Firmware itself is always platform specific. So the most close virtualization is let gvt virtualize GPU HW, and firmware virtualize opregion.

However in QEMU world, it looks like those non-simulated device related opreations are left to other component as most as possible, like VFIO region, so that QEMU itself could force less on physical device specific operations but handle the common logic. In this opregion case, QEMU and seabios only copies the raw data, but the contents are left to gvt to fill so that gvt could fill different data in different cases. Otherwise any change requires SEABIOS update, instead of dyncamilly filled by gvt.

One benefit OVMF overcomes SEABIOS is that IntelGvtGopDxe can be loaded
as a standalone driver. So it maybe possible that in OVMF case, both gvt and IntelGvtGopDxe can act part of Intel vGPU virtualization component. However the behavior of gvt+seabios and gvt+ovmf will be inconsistent. May need update gvt logic so that if IntelGvtGopDxe generate opregion, gvt can still update it before any opregion consumer using it. Then, loading fw_cfg can be dropped without preventing guest OS driver find it.

I'm adding gvt maintainer here for more comments.

Failing that we should at least take fw_cfg out of the loop. It is just
a middle man here and not needed at all. As discussed before the pci
rom bar can do the job instead. That will remove any platform
dependencies from the driver, it only need to talk to the device itself
then.

take care,
Gerd

--
Best Regards,
Colin Xu


Gerd Hoffmann
 

Hi,

operations but handle the common logic. In this opregion case, QEMU and
seabios only copies the raw data, but the contents are left to gvt to fill
so that gvt could fill different data in different cases.
Yes, gvt could do that.

The big question is: does that actually happen? When looking at
drivers/gpu/drm/i915/gvt/opregion.c it seems the opregion is pretty
static.

Are there plausible reasons for that capability being needed in the
future?

Otherwise any change requires SEABIOS update, instead of dyncamilly
filled by gvt.
That clearly isn't an option.

One benefit OVMF overcomes SEABIOS is that IntelGvtGopDxe can be loaded
as a standalone driver.
Well, seabios allows standalone drivers too. It's called vgabios ;)

So it maybe possible that in OVMF case, both gvt and
IntelGvtGopDxe can act part of Intel vGPU virtualization component. However
the behavior of gvt+seabios and gvt+ovmf will be inconsistent.
Well, in case the opregion is not static there is still the option to
use the pci rom bar instead of fw_cfg to deliver the opregion content
to the guest.

May need
update gvt logic so that if IntelGvtGopDxe generate opregion, gvt can still
update it before any opregion consumer using it.
Hmm. Can gvt trap pci config space writes? IIRC pci config space is
simply yet another vfio region, so that should be possible. gvt could
update the opregion then when the firmware updates the opregion address.

If that actually works there is little reason for IntelGvtGopDxe (and
seabios) to fill the opregion in the first place though. We could
change the opregion initialization protocol to something like this:

(1) firmware allocates memory for the opregion
(2) firmware fills signature and size
(3) firmware writes opregion address to pci config space
(4) gvt goes fill opregion at the given address in guest memory.

Maybe it would be better to reserve a paravirtual mmio register for that
purpose to make the whole thing a bit more robust.

Then, loading fw_cfg can be
dropped without preventing guest OS driver find it.
I guess we have to keep that for a while for backward compatibility
reasons.

take care,
Gerd


Colin Xu
 

On Fri, 19 Mar 2021, Gerd Hoffmann wrote:

Hi,

operations but handle the common logic. In this opregion case, QEMU and
seabios only copies the raw data, but the contents are left to gvt to fill
so that gvt could fill different data in different cases.
Yes, gvt could do that.

The big question is: does that actually happen? When looking at
drivers/gpu/drm/i915/gvt/opregion.c it seems the opregion is pretty
static.

Are there plausible reasons for that capability being needed in the
future?
The current situation is static indeed. However there are still two cases requires run-time adjustment.
1) Current opregion/vbt has fixed display mappings, and many virtual GPU registers' value are inherited from host. However host opregion/vbt is platform specific. So if guest driver (like i915) do some strict sanity check it will found some display registers are incorrect. The proper way is that gvt generate vbt based on the virutal display type it emulated, and initialze related vREGs by following VESA and Intel specs.
2) Some downstream project may use physical display as an output, thus also need generate VBT based on host opregion/vbt.

Otherwise any change requires SEABIOS update, instead of dyncamilly
filled by gvt.
That clearly isn't an option.
Yes, so based on such reason, gvt should still be able to update it dynamically even ovmf/seabios can generate the initial value.
One benefit OVMF overcomes SEABIOS is that IntelGvtGopDxe can be loaded
as a standalone driver.
Well, seabios allows standalone drivers too. It's called vgabios ;)
Like ATI VGABIOS in seabios repo. Unfortunately Intel hasn't implemented yet.
So it maybe possible that in OVMF case, both gvt and
IntelGvtGopDxe can act part of Intel vGPU virtualization component. However
the behavior of gvt+seabios and gvt+ovmf will be inconsistent.
Well, in case the opregion is not static there is still the option to
use the pci rom bar instead of fw_cfg to deliver the opregion content
to the guest.

May need
update gvt logic so that if IntelGvtGopDxe generate opregion, gvt can still
update it before any opregion consumer using it.
Hmm. Can gvt trap pci config space writes? IIRC pci config space is
simply yet another vfio region, so that should be possible. gvt could
update the opregion then when the firmware updates the opregion address.

If that actually works there is little reason for IntelGvtGopDxe (and
seabios) to fill the opregion in the first place though. We could
change the opregion initialization protocol to something like this:

(1) firmware allocates memory for the opregion
(2) firmware fills signature and size
(3) firmware writes opregion address to pci config space
(4) gvt goes fill opregion at the given address in guest memory.

Maybe it would be better to reserve a paravirtual mmio register for that
purpose to make the whole thing a bit more robust.
Yes gvt can trap PCI cfg read/write, the suggested protocol is exact the same as I'm considering. Let me refine this big patch to smaller ones and send out again. Thanks very much!

Then, loading fw_cfg can be
dropped without preventing guest OS driver find it.
I guess we have to keep that for a while for backward compatibility
reasons.
Sure. That will be the correct way.

take care,
Gerd

--
Best Regards,
Colin Xu