LyoKICogQ29weXJpZ2h0IDIwMDYgVHVuZ3N0ZW4gR3JhcGhpY3MgSW5jLiwgQmlzbWFyY2ssIE5ELiwgVVNBLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLgogKgogKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYQogKiBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLAogKiB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uCiAqIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwKICogYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlCiAqIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CiAqCiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIChpbmNsdWRpbmcgdGhlCiAqIG5leHQgcGFyYWdyYXBoKSBzaGFsbCBiZSBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zCiAqIG9mIHRoZSBTb2Z0d2FyZS4KICoKICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IKICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT04tSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTAogKiBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBBTkQvT1IgVEhFSVIgU1VQUExJRVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLAogKiBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLAogKiBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIKICogREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgogKi8KLyoKICogQXV0aG9yczogVGhvbWFzIEhlbGxzdHL2bSA8dGhvbWFzLWF0LXR1bmdzdGVuZ3JhcGhpY3MtZG90LWNvbT4KICovCgojaW5jbHVkZSAiZHJtUC5oIgojaW5jbHVkZSAidmlhX2RybS5oIgojaW5jbHVkZSAidmlhX2Rydi5oIgojaW5jbHVkZSAiZHJtX3NtYW4uaCIKCiNkZWZpbmUgVklBX01NX0FMSUdOX1NISUZUIDQKI2RlZmluZSBWSUFfTU1fQUxJR05fTUFTSyAoICgxIDw8IFZJQV9NTV9BTElHTl9TSElGVCkgLSAxKQoKaW50IHZpYV9hZ3BfaW5pdChEUk1fSU9DVExfQVJHUykKewoJRFJNX0RFVklDRTsKCWRybV92aWFfYWdwX3QgYWdwOwoJZHJtX3ZpYV9wcml2YXRlX3QgKmRldl9wcml2ID0gKGRybV92aWFfcHJpdmF0ZV90ICopIGRldi0+ZGV2X3ByaXZhdGU7CglpbnQgcmV0OwoKCURSTV9DT1BZX0ZST01fVVNFUl9JT0NUTChhZ3AsIChkcm1fdmlhX2FncF90IF9fdXNlciAqKSBkYXRhLAoJCQkJIHNpemVvZihhZ3ApKTsKCW11dGV4X2xvY2soJmRldi0+c3RydWN0X211dGV4KTsKCXJldCA9IGRybV9zbWFuX3NldF9yYW5nZSgmZGV2X3ByaXYtPnNtYW4sIFZJQV9NRU1fQUdQLCAwLAoJCQkJIGFncC5zaXplID4+IFZJQV9NTV9BTElHTl9TSElGVCk7CgoJaWYgKHJldCkgewoJCURSTV9FUlJPUigiQUdQIG1lbW9yeSBtYW5hZ2VyIGluaXRpYWxpc2F0aW9uIGVycm9yXG4iKTsKCQltdXRleF91bmxvY2soJmRldi0+c3RydWN0X211dGV4KTsKCQlyZXR1cm4gcmV0OwoJfQoKCWRldl9wcml2LT5hZ3BfaW5pdGlhbGl6ZWQgPSAxOwoJZGV2X3ByaXYtPmFncF9vZmZzZXQgPSBhZ3Aub2Zmc2V0OwoJbXV0ZXhfdW5sb2NrKCZkZXYtPnN0cnVjdF9tdXRleCk7CgoJRFJNX0RFQlVHKCJvZmZzZXQgPSAldSwgc2l6ZSA9ICV1IiwgYWdwLm9mZnNldCwgYWdwLnNpemUpOwoJcmV0dXJuIDA7Cn0KCmludCB2aWFfZmJfaW5pdChEUk1fSU9DVExfQVJHUykKewoJRFJNX0RFVklDRTsKCWRybV92aWFfZmJfdCBmYjsKCWRybV92aWFfcHJpdmF0ZV90ICpkZXZfcHJpdiA9IChkcm1fdmlhX3ByaXZhdGVfdCAqKSBkZXYtPmRldl9wcml2YXRlOwoJaW50IHJldDsKCglEUk1fQ09QWV9GUk9NX1VTRVJfSU9DVEwoZmIsIChkcm1fdmlhX2ZiX3QgX191c2VyICopIGRhdGEsIHNpemVvZihmYikpOwoKCW11dGV4X2xvY2soJmRldi0+c3RydWN0X211dGV4KTsKCXJldCA9IGRybV9zbWFuX3NldF9yYW5nZSgmZGV2X3ByaXYtPnNtYW4sIFZJQV9NRU1fVklERU8sIDAsCgkJCQkgZmIuc2l6ZSA+PiBWSUFfTU1fQUxJR05fU0hJRlQpOwoKCWlmIChyZXQpIHsKCQlEUk1fRVJST1IoIlZSQU0gbWVtb3J5IG1hbmFnZXIgaW5pdGlhbGlzYXRpb24gZXJyb3JcbiIpOwoJCW11dGV4X3VubG9jaygmZGV2LT5zdHJ1Y3RfbXV0ZXgpOwoJCXJldHVybiByZXQ7Cgl9CgoJZGV2X3ByaXYtPnZyYW1faW5pdGlhbGl6ZWQgPSAxOwoJZGV2X3ByaXYtPnZyYW1fb2Zmc2V0ID0gZmIub2Zmc2V0OwoKCW11dGV4X3VubG9jaygmZGV2LT5zdHJ1Y3RfbXV0ZXgpOwoJRFJNX0RFQlVHKCJvZmZzZXQgPSAldSwgc2l6ZSA9ICV1IiwgZmIub2Zmc2V0LCBmYi5zaXplKTsKCglyZXR1cm4gMDsKCn0KCmludCB2aWFfZmluYWxfY29udGV4dChzdHJ1Y3QgZHJtX2RldmljZSAqZGV2LCBpbnQgY29udGV4dCkKewoJZHJtX3ZpYV9wcml2YXRlX3QgKmRldl9wcml2ID0gKGRybV92aWFfcHJpdmF0ZV90ICopIGRldi0+ZGV2X3ByaXZhdGU7CgoJdmlhX3JlbGVhc2VfZnV0ZXgoZGV2X3ByaXYsIGNvbnRleHQpOwoKCS8qIExpbnV4IHNwZWNpZmljIHVudGlsIGNvbnRleHQgdHJhY2tpbmcgY29kZSBnZXRzIHBvcnRlZCB0byBCU0QgKi8KCS8qIExhc3QgY29udGV4dCwgcGVyZm9ybSBjbGVhbnVwICovCglpZiAoZGV2LT5jdHhfY291bnQgPT0gMSAmJiBkZXYtPmRldl9wcml2YXRlKSB7CgkJRFJNX0RFQlVHKCJMYXN0IENvbnRleHRcbiIpOwoJCWlmIChkZXYtPmlycSkKCQkJZHJtX2lycV91bmluc3RhbGwoZGV2KTsKCQl2aWFfY2xlYW51cF9mdXRleChkZXZfcHJpdik7CgkJdmlhX2RvX2NsZWFudXBfbWFwKGRldik7Cgl9CglyZXR1cm4gMTsKfQoKdm9pZCB2aWFfbGFzdGNsb3NlKHN0cnVjdCBkcm1fZGV2aWNlICpkZXYpCnsKCWRybV92aWFfcHJpdmF0ZV90ICpkZXZfcHJpdiA9IChkcm1fdmlhX3ByaXZhdGVfdCAqKSBkZXYtPmRldl9wcml2YXRlOwoKCWlmICghZGV2X3ByaXYpCgkJcmV0dXJuOwoKCW11dGV4X2xvY2soJmRldi0+c3RydWN0X211dGV4KTsKCWRybV9zbWFuX2NsZWFudXAoJmRldl9wcml2LT5zbWFuKTsKCWRldl9wcml2LT52cmFtX2luaXRpYWxpemVkID0gMDsKCWRldl9wcml2LT5hZ3BfaW5pdGlhbGl6ZWQgPSAwOwoJbXV0ZXhfdW5sb2NrKCZkZXYtPnN0cnVjdF9tdXRleCk7Cn0JCgppbnQgdmlhX21lbV9hbGxvYyhEUk1fSU9DVExfQVJHUykKewoJRFJNX0RFVklDRTsKCglkcm1fdmlhX21lbV90IG1lbTsKCWludCByZXR2YWwgPSAwOwoJZHJtX21lbWJsb2NrX2l0ZW1fdCAqaXRlbTsKCWRybV92aWFfcHJpdmF0ZV90ICpkZXZfcHJpdiA9IChkcm1fdmlhX3ByaXZhdGVfdCAqKSBkZXYtPmRldl9wcml2YXRlOwoJdW5zaWduZWQgbG9uZyB0bXBTaXplOwoKCURSTV9DT1BZX0ZST01fVVNFUl9JT0NUTChtZW0sIChkcm1fdmlhX21lbV90IF9fdXNlciAqKSBkYXRhLAoJCQkJIHNpemVvZihtZW0pKTsKCglpZiAobWVtLnR5cGUgPiBWSUFfTUVNX0FHUCkgewoJCURSTV9FUlJPUigiVW5rbm93biBtZW1vcnkgdHlwZSBhbGxvY2F0aW9uXG4iKTsKCQlyZXR1cm4gRFJNX0VSUihFSU5WQUwpOwoJfQoJbXV0ZXhfbG9jaygmZGV2LT5zdHJ1Y3RfbXV0ZXgpOwoJaWYgKDAgPT0gKChtZW0udHlwZSA9PSBWSUFfTUVNX1ZJREVPKSA/IGRldl9wcml2LT52cmFtX2luaXRpYWxpemVkIDoKCQkgICAgICBkZXZfcHJpdi0+YWdwX2luaXRpYWxpemVkKSkgewoJCURSTV9FUlJPUgoJCSAgICAoIkF0dGVtcHQgdG8gYWxsb2NhdGUgZnJvbSB1bmluaXRpYWxpemVkIG1lbW9yeSBtYW5hZ2VyLlxuIik7CgkJbXV0ZXhfdW5sb2NrKCZkZXYtPnN0cnVjdF9tdXRleCk7CgkJcmV0dXJuIERSTV9FUlIoRUlOVkFMKTsKCX0KCgl0bXBTaXplID0gKG1lbS5zaXplICsgVklBX01NX0FMSUdOX01BU0spID4+IFZJQV9NTV9BTElHTl9TSElGVDsKCWl0ZW0gPSBkcm1fc21hbl9hbGxvYygmZGV2X3ByaXYtPnNtYW4sIG1lbS50eXBlLCB0bXBTaXplLCAwLAoJCQkgICAgICAodW5zaWduZWQgbG9uZylwcml2KTsKCW11dGV4X3VubG9jaygmZGV2LT5zdHJ1Y3RfbXV0ZXgpOwoJaWYgKGl0ZW0pIHsKCQltZW0ub2Zmc2V0ID0gKChtZW0udHlwZSA9PSBWSUFfTUVNX1ZJREVPKSA/CgkJCSAgICAgIGRldl9wcml2LT52cmFtX29mZnNldCA6IGRldl9wcml2LT5hZ3Bfb2Zmc2V0KSArCgkJICAgIChpdGVtLT5tbS0+CgkJICAgICBvZmZzZXQoaXRlbS0+bW0sIGl0ZW0tPm1tX2luZm8pIDw8IFZJQV9NTV9BTElHTl9TSElGVCk7CgkJbWVtLmluZGV4ID0gaXRlbS0+dXNlcl9oYXNoLmtleTsKCX0gZWxzZSB7CgkJbWVtLm9mZnNldCA9IDA7CgkJbWVtLnNpemUgPSAwOwoJCW1lbS5pbmRleCA9IDA7CgkJRFJNX0RFQlVHKCJWaWRlbyBtZW1vcnkgYWxsb2NhdGlvbiBmYWlsZWRcbiIpOwoJCXJldHZhbCA9IERSTV9FUlIoRU5PTUVNKTsKCX0KCURSTV9DT1BZX1RPX1VTRVJfSU9DVEwoKGRybV92aWFfbWVtX3QgX191c2VyICopIGRhdGEsIG1lbSwgc2l6ZW9mKG1lbSkpOwoKCXJldHVybiByZXR2YWw7Cn0KCmludCB2aWFfbWVtX2ZyZWUoRFJNX0lPQ1RMX0FSR1MpCnsKCURSTV9ERVZJQ0U7Cglkcm1fdmlhX3ByaXZhdGVfdCAqZGV2X3ByaXYgPSBkZXYtPmRldl9wcml2YXRlOwoJZHJtX3ZpYV9tZW1fdCBtZW07CglpbnQgcmV0OwoKCURSTV9DT1BZX0ZST01fVVNFUl9JT0NUTChtZW0sIChkcm1fdmlhX21lbV90IF9fdXNlciAqKSBkYXRhLAoJCQkJIHNpemVvZihtZW0pKTsKCgltdXRleF9sb2NrKCZkZXYtPnN0cnVjdF9tdXRleCk7CglyZXQgPSBkcm1fc21hbl9mcmVlX2tleSgmZGV2X3ByaXYtPnNtYW4sIG1lbS5pbmRleCk7CgltdXRleF91bmxvY2soJmRldi0+c3RydWN0X211dGV4KTsKCURSTV9ERUJVRygiZnJlZSA9IDB4JWx4XG4iLCBtZW0uaW5kZXgpOwoKCXJldHVybiByZXQ7Cn0KCgp2b2lkIHZpYV9yZWNsYWltX2J1ZmZlcnNfbG9ja2VkKGRybV9kZXZpY2VfdCAqIGRldiwgc3RydWN0IGZpbGUgKmZpbHApCnsKCWRybV92aWFfcHJpdmF0ZV90ICpkZXZfcHJpdiA9IGRldi0+ZGV2X3ByaXZhdGU7Cglkcm1fZmlsZV90ICpwcml2ID0gZmlscC0+cHJpdmF0ZV9kYXRhOwoKCW11dGV4X2xvY2soJmRldi0+c3RydWN0X211dGV4KTsKCWlmIChkcm1fc21hbl9vd25lcl9jbGVhbigmZGV2X3ByaXYtPnNtYW4sICh1bnNpZ25lZCBsb25nKXByaXYpKSB7CgkJbXV0ZXhfdW5sb2NrKCZkZXYtPnN0cnVjdF9tdXRleCk7CgkJcmV0dXJuOwoJfQoKCWlmIChkZXYtPmRyaXZlci0+ZG1hX3F1aWVzY2VudCkgewoJCWRldi0+ZHJpdmVyLT5kbWFfcXVpZXNjZW50KGRldik7Cgl9CgoJZHJtX3NtYW5fb3duZXJfY2xlYW51cCgmZGV2X3ByaXYtPnNtYW4sICh1bnNpZ25lZCBsb25nKXByaXYpOwoJbXV0ZXhfdW5sb2NrKCZkZXYtPnN0cnVjdF9tdXRleCk7CglyZXR1cm47Cn0K