LyoKICogKEMpIENvcHlyaWdodCAyMDA4LDIwMDkKICogR3JhZW1lIFJ1c3MsIDxncmFlbWUucnVzc0BnbWFpbC5jb20+CiAqCiAqIChDKSBDb3B5cmlnaHQgMjAwMgogKiBEYW5pZWwgRW5nc3Ry9m0sIE9taWNyb24gQ2V0aSBBQiwgPGRhbmllbEBvbWljcm9uLnNlPgogKgogKiBTZWUgZmlsZSBDUkVESVRTIGZvciBsaXN0IG9mIHBlb3BsZSB3aG8gY29udHJpYnV0ZWQgdG8gdGhpcwogKiBwcm9qZWN0LgogKgogKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzCiAqIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mCiAqIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLgkgU2VlIHRoZQogKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogKgogKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQogKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLAogKiBNQSAwMjExMS0xMzA3IFVTQQogKi8KCiNpbmNsdWRlIDxjb21tb24uaD4KI2luY2x1ZGUgPHBjaS5oPgojaW5jbHVkZSA8YXNtL3BjaS5oPgojaW5jbHVkZSA8YXNtL2ljL3BjaS5oPgoKc3RhdGljIHZvaWQgcGNpX2VuZXRfZml4dXBfaXJxKHN0cnVjdCBwY2lfY29udHJvbGxlciAqaG9zZSwgcGNpX2Rldl90IGRldikKewoJLyogYSBjb25maWd1cmFibGUgbGlzdHMgb2YgSVJRcyB0byBzdGVhbCB3aGVuIHdlIG5lZWQgb25lICovCglzdGF0aWMgaW50IGlycV9saXN0W10gPSB7CgkJQ09ORklHX1NZU19GSVJTVF9QQ0lfSVJRLAoJCUNPTkZJR19TWVNfU0VDT05EX1BDSV9JUlEsCgkJQ09ORklHX1NZU19USElSRF9QQ0lfSVJRLAoJCUNPTkZJR19TWVNfRk9SVEhfUENJX0lSUQoJfTsKCXN0YXRpYyBpbnQgbmV4dF9pcnFfaW5kZXg9MDsKCgl1Y2hhciB0bXBfcGluOwoJaW50IHBpbjsKCglwY2lfaG9zZV9yZWFkX2NvbmZpZ19ieXRlKGhvc2UsIGRldiwgUENJX0lOVEVSUlVQVF9QSU4sICZ0bXBfcGluKTsKCXBpbiA9IHRtcF9waW47CgoJcGluIC09IDE7IC8qIFBDSSBjb25maWcgc3BhY2UgdXNlIDEtYmFzZWQgbnVtYmVyaW5nICovCglpZiAocGluID09IC0xKSB7CgkJcmV0dXJuOyAvKiBkZXZpY2UgdXNlIG5vIGlycSAqLwoJfQoKCS8qIG1hcCBkZXZpY2UgbnVtYmVyICsgIHBpbiB0byBhIHBpbiBvbiB0aGUgc2M1MjAgKi8KCXN3aXRjaCAoUENJX0RFVihkZXYpKSB7CgljYXNlIDEyOgkvKiBGaXJzdCBFdGhlcm5ldCBDaGlwICovCgkJcGluICs9IFNDNTIwX1BDSV9JTlRBOwoJCWJyZWFrOwoKCWNhc2UgMTM6CS8qIFNlY29uZCBFdGhlcm5ldCBDaGlwICovCgkJcGluICs9IFNDNTIwX1BDSV9JTlRCOwoJCWJyZWFrOwoKCWRlZmF1bHQ6CgkJcmV0dXJuOwoJfQoKCXBpbiAmPSAzOyAvKiB3cmFwIGFyb3VuZCAqLwoKCWlmIChzYzUyMF9wY2lfaW50c1twaW5dID09IC0xKSB7CgkJLyogcmUtcm91dGUgb25lIGludGVycnVwdCBmb3IgdXMgKi8KCQlpZiAobmV4dF9pcnFfaW5kZXggPiAzKSB7CgkJCXJldHVybjsKCQl9CgkJaWYgKHBjaV9zYzUyMF9zZXRfaXJxKHBpbiwgaXJxX2xpc3RbbmV4dF9pcnFfaW5kZXhdKSkgewoJCQlyZXR1cm47CgkJfQoJCW5leHRfaXJxX2luZGV4Kys7Cgl9CgoJaWYgKC0xICE9IHNjNTIwX3BjaV9pbnRzW3Bpbl0pIHsKCXBjaV9ob3NlX3dyaXRlX2NvbmZpZ19ieXRlKGhvc2UsIGRldiwgUENJX0lOVEVSUlVQVF9MSU5FLAoJCQkJCSAgIHNjNTIwX3BjaV9pbnRzW3Bpbl0pOwoJfQoJcHJpbnRmKCJmaXh1cF9pcnE6IGRldmljZSAlZCBwaW4gJWMgaXJxICVkXG4iLAoJICAgICAgIFBDSV9ERVYoZGV2KSwgJ0EnICsgcGluLCBzYzUyMF9wY2lfaW50c1twaW5dKTsKfQoKc3RhdGljIHN0cnVjdCBwY2lfY29udHJvbGxlciBlbmV0X2hvc2UgPSB7CglmaXh1cF9pcnE6IHBjaV9lbmV0X2ZpeHVwX2lycSwKfTsKCnZvaWQgcGNpX2luaXRfYm9hcmQodm9pZCkKewoJcGNpX3NjNTIwX2luaXQoJmVuZXRfaG9zZSk7Cn0KCmludCBwY2lfc2V0X3JlZ2lvbnMoc3RydWN0IHBjaV9jb250cm9sbGVyICpob3NlKQp7CgkvKiBTeXN0ZW0gbWVtb3J5IHNwYWNlICovCglwY2lfc2V0X3JlZ2lvbihob3NlLT5yZWdpb25zICsgMCwKCQkgICAgICAgU0M1MjBfUENJX01FTU9SWV9CVVMsCgkJICAgICAgIFNDNTIwX1BDSV9NRU1PUllfUEhZUywKCQkgICAgICAgU0M1MjBfUENJX01FTU9SWV9TSVpFLAoJCSAgICAgICBQQ0lfUkVHSU9OX01FTSB8IFBDSV9SRUdJT05fU1lTX01FTU9SWSk7CgoJLyogSVNBL1BDSSBtZW1vcnkgc3BhY2UgKi8KCXBjaV9zZXRfcmVnaW9uKGhvc2UtPnJlZ2lvbnMgKyAxLAoJCSAgICAgICBTQzUyMF9JU0FfTUVNX0JVUywKCQkgICAgICAgU0M1MjBfSVNBX01FTV9QSFlTLAoJCSAgICAgICBTQzUyMF9JU0FfTUVNX1NJWkUsCgkJICAgICAgIFBDSV9SRUdJT05fTUVNKTsKCgkvKiBQQ0kgSS9PIHNwYWNlICovCglwY2lfc2V0X3JlZ2lvbihob3NlLT5yZWdpb25zICsgMiwKCQkgICAgICAgU0M1MjBfUENJX0lPX0JVUywKCQkgICAgICAgU0M1MjBfUENJX0lPX1BIWVMsCgkJICAgICAgIFNDNTIwX1BDSV9JT19TSVpFLAoJCSAgICAgICBQQ0lfUkVHSU9OX0lPKTsKCgkvKiBJU0EvUENJIEkvTyBzcGFjZSAqLwoJcGNpX3NldF9yZWdpb24oaG9zZS0+cmVnaW9ucyArIDMsCgkJICAgICAgIFNDNTIwX0lTQV9JT19CVVMsCgkJICAgICAgIFNDNTIwX0lTQV9JT19QSFlTLAoJCSAgICAgICBTQzUyMF9JU0FfSU9fU0laRSwKCQkgICAgICAgUENJX1JFR0lPTl9JTyk7CgoJcmV0dXJuIDQ7Cn0K