LyoKICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogQ29weXJpZ2h0IChDKSBKb25hdGhhbiBOYXlsb3IgRzRLTFggKGc0a2x4QGc0a2x4LmRlbW9uLmNvLnVrKQogKiBDb3B5cmlnaHQgKEMpIEpvZXJnIFJldXRlciBETDFCS0UgKGpyZXV0ZXJAeWFpbmEuZGUpCiAqLwojaW5jbHVkZSA8bGludXgvZXJybm8uaD4KI2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+CiNpbmNsdWRlIDxsaW51eC9zb2NrZXQuaD4KI2luY2x1ZGUgPGxpbnV4L2luLmg+CiNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KI2luY2x1ZGUgPGxpbnV4L3NjaGVkLmg+CiNpbmNsdWRlIDxsaW51eC90aW1lci5oPgojaW5jbHVkZSA8bGludXgvc3RyaW5nLmg+CiNpbmNsdWRlIDxsaW51eC9zb2NraW9zLmg+CiNpbmNsdWRlIDxsaW51eC9uZXQuaD4KI2luY2x1ZGUgPG5ldC9heDI1Lmg+CiNpbmNsdWRlIDxsaW51eC9pbmV0Lmg+CiNpbmNsdWRlIDxsaW51eC9uZXRkZXZpY2UuaD4KI2luY2x1ZGUgPGxpbnV4L3NrYnVmZi5oPgojaW5jbHVkZSA8bmV0L3NvY2suaD4KI2luY2x1ZGUgPG5ldC90Y3Bfc3RhdGVzLmg+CiNpbmNsdWRlIDxhc20vdWFjY2Vzcy5oPgojaW5jbHVkZSA8YXNtL3N5c3RlbS5oPgojaW5jbHVkZSA8bGludXgvZmNudGwuaD4KI2luY2x1ZGUgPGxpbnV4L21tLmg+CiNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4KCi8qCiAqCVN0YXRlIG1hY2hpbmUgZm9yIHN0YXRlIDEsIEF3YWl0aW5nIENvbm5lY3Rpb24gU3RhdGUuCiAqCVRoZSBoYW5kbGluZyBvZiB0aGUgdGltZXIocykgaXMgaW4gZmlsZSBheDI1X2RzX3RpbWVyLmMuCiAqCUhhbmRsaW5nIG9mIHN0YXRlIDAgYW5kIGNvbm5lY3Rpb24gcmVsZWFzZSBpcyBpbiBheDI1LmMuCiAqLwpzdGF0aWMgaW50IGF4MjVfZHNfc3RhdGUxX21hY2hpbmUoYXgyNV9jYiAqYXgyNSwgc3RydWN0IHNrX2J1ZmYgKnNrYiwgaW50IGZyYW1ldHlwZSwgaW50IHBmLCBpbnQgdHlwZSkKewoJc3dpdGNoIChmcmFtZXR5cGUpIHsKCWNhc2UgQVgyNV9TQUJNOgoJCWF4MjUtPm1vZHVsdXMgPSBBWDI1X01PRFVMVVM7CgkJYXgyNS0+d2luZG93ICA9IGF4MjUtPmF4MjVfZGV2LT52YWx1ZXNbQVgyNV9WQUxVRVNfV0lORE9XXTsKCQlheDI1X3NlbmRfY29udHJvbChheDI1LCBBWDI1X1VBLCBwZiwgQVgyNV9SRVNQT05TRSk7CgkJYnJlYWs7CgoJY2FzZSBBWDI1X1NBQk1FOgoJCWF4MjUtPm1vZHVsdXMgPSBBWDI1X0VNT0RVTFVTOwoJCWF4MjUtPndpbmRvdyAgPSAgYXgyNS0+YXgyNV9kZXYtPnZhbHVlc1tBWDI1X1ZBTFVFU19FV0lORE9XXTsKCQlheDI1X3NlbmRfY29udHJvbChheDI1LCBBWDI1X1VBLCBwZiwgQVgyNV9SRVNQT05TRSk7CgkJYnJlYWs7CgoJY2FzZSBBWDI1X0RJU0M6CgkJYXgyNV9zZW5kX2NvbnRyb2woYXgyNSwgQVgyNV9ETSwgcGYsIEFYMjVfUkVTUE9OU0UpOwoJCWJyZWFrOwoKCWNhc2UgQVgyNV9VQToKCQlheDI1X2NhbGN1bGF0ZV9ydHQoYXgyNSk7CgkJYXgyNV9zdG9wX3QxdGltZXIoYXgyNSk7CgkJYXgyNV9zdGFydF90M3RpbWVyKGF4MjUpOwoJCWF4MjVfc3RhcnRfaWRsZXRpbWVyKGF4MjUpOwoJCWF4MjUtPnZzICAgICAgPSAwOwoJCWF4MjUtPnZhICAgICAgPSAwOwoJCWF4MjUtPnZyICAgICAgPSAwOwoJCWF4MjUtPnN0YXRlICAgPSBBWDI1X1NUQVRFXzM7CgkJYXgyNS0+bjJjb3VudCA9IDA7CgkJaWYgKGF4MjUtPnNrICE9IE5VTEwpIHsKCQkJYmhfbG9ja19zb2NrKGF4MjUtPnNrKTsKCQkJYXgyNS0+c2stPnNrX3N0YXRlID0gVENQX0VTVEFCTElTSEVEOwoJCQkvKgoJCQkgKiBGb3IgV0FJVF9TQUJNIGNvbm5lY3Rpb25zIHdlIHdpbGwgcHJvZHVjZSBhbiBhY2NlcHQKCQkJICogcmVhZHkgc29ja2V0IGhlcmUKCQkJICovCgkJCWlmICghc29ja19mbGFnKGF4MjUtPnNrLCBTT0NLX0RFQUQpKQoJCQkJYXgyNS0+c2stPnNrX3N0YXRlX2NoYW5nZShheDI1LT5zayk7CgkJCWJoX3VubG9ja19zb2NrKGF4MjUtPnNrKTsKCQl9CgkJYXgyNV9kYW1hX29uKGF4MjUpOwoKCQkvKiBhY2NvcmRpbmcgdG8gREs0RUe0cyBzcGVjIHdlIGFyZSByZXF1aXJlZCB0bwoJCSAqIHNlbmQgYSBSUiBSRVNQT05TRSBGSU5BTCBOUj0wLgoJCSAqLwoKCQlheDI1X3N0ZF9lbnF1aXJ5X3Jlc3BvbnNlKGF4MjUpOwoJCWJyZWFrOwoKCWNhc2UgQVgyNV9ETToKCQlpZiAocGYpCgkJCWF4MjVfZGlzY29ubmVjdChheDI1LCBFQ09OTlJFRlVTRUQpOwoJCWJyZWFrOwoKCWRlZmF1bHQ6CgkJaWYgKHBmKQoJCQlheDI1X3NlbmRfY29udHJvbChheDI1LCBBWDI1X1NBQk0sIEFYMjVfUE9MTE9OLCBBWDI1X0NPTU1BTkQpOwoJCWJyZWFrOwoJfQoKCXJldHVybiAwOwp9CgovKgogKglTdGF0ZSBtYWNoaW5lIGZvciBzdGF0ZSAyLCBBd2FpdGluZyBSZWxlYXNlIFN0YXRlLgogKglUaGUgaGFuZGxpbmcgb2YgdGhlIHRpbWVyKHMpIGlzIGluIGZpbGUgYXgyNV9kc190aW1lci5jCiAqCUhhbmRsaW5nIG9mIHN0YXRlIDAgYW5kIGNvbm5lY3Rpb24gcmVsZWFzZSBpcyBpbiBheDI1LmMuCiAqLwpzdGF0aWMgaW50IGF4MjVfZHNfc3RhdGUyX21hY2hpbmUoYXgyNV9jYiAqYXgyNSwgc3RydWN0IHNrX2J1ZmYgKnNrYiwgaW50IGZyYW1ldHlwZSwgaW50IHBmLCBpbnQgdHlwZSkKewoJc3dpdGNoIChmcmFtZXR5cGUpIHsKCWNhc2UgQVgyNV9TQUJNOgoJY2FzZSBBWDI1X1NBQk1FOgoJCWF4MjVfc2VuZF9jb250cm9sKGF4MjUsIEFYMjVfRElTQywgQVgyNV9QT0xMT04sIEFYMjVfQ09NTUFORCk7CgkJYXgyNV9kYW1hX29mZihheDI1KTsKCQlicmVhazsKCgljYXNlIEFYMjVfRElTQzoKCQlheDI1X3NlbmRfY29udHJvbChheDI1LCBBWDI1X1VBLCBwZiwgQVgyNV9SRVNQT05TRSk7CgkJYXgyNV9kYW1hX29mZihheDI1KTsKCQlheDI1X2Rpc2Nvbm5lY3QoYXgyNSwgMCk7CgkJYnJlYWs7CgoJY2FzZSBBWDI1X0RNOgoJY2FzZSBBWDI1X1VBOgoJCWlmIChwZikgewoJCQlheDI1X2RhbWFfb2ZmKGF4MjUpOwoJCQlheDI1X2Rpc2Nvbm5lY3QoYXgyNSwgMCk7CgkJfQoJCWJyZWFrOwoKCWNhc2UgQVgyNV9JOgoJY2FzZSBBWDI1X1JFSjoKCWNhc2UgQVgyNV9STlI6CgljYXNlIEFYMjVfUlI6CgkJaWYgKHBmKSB7CgkJCWF4MjVfc2VuZF9jb250cm9sKGF4MjUsIEFYMjVfRElTQywgQVgyNV9QT0xMT04sIEFYMjVfQ09NTUFORCk7CgkJCWF4MjVfZGFtYV9vZmYoYXgyNSk7CgkJfQoJCWJyZWFrOwoKCWRlZmF1bHQ6CgkJYnJlYWs7Cgl9CgoJcmV0dXJuIDA7Cn0KCi8qCiAqCVN0YXRlIG1hY2hpbmUgZm9yIHN0YXRlIDMsIENvbm5lY3RlZCBTdGF0ZS4KICoJVGhlIGhhbmRsaW5nIG9mIHRoZSB0aW1lcihzKSBpcyBpbiBmaWxlIGF4MjVfdGltZXIuYwogKglIYW5kbGluZyBvZiBzdGF0ZSAwIGFuZCBjb25uZWN0aW9uIHJlbGVhc2UgaXMgaW4gYXgyNS5jLgogKi8Kc3RhdGljIGludCBheDI1X2RzX3N0YXRlM19tYWNoaW5lKGF4MjVfY2IgKmF4MjUsIHN0cnVjdCBza19idWZmICpza2IsIGludCBmcmFtZXR5cGUsIGludCBucywgaW50IG5yLCBpbnQgcGYsIGludCB0eXBlKQp7CglpbnQgcXVldWVkID0gMDsKCglzd2l0Y2ggKGZyYW1ldHlwZSkgewoJY2FzZSBBWDI1X1NBQk06CgljYXNlIEFYMjVfU0FCTUU6CgkJaWYgKGZyYW1ldHlwZSA9PSBBWDI1X1NBQk0pIHsKCQkJYXgyNS0+bW9kdWx1cyAgID0gQVgyNV9NT0RVTFVTOwoJCQlheDI1LT53aW5kb3cgICAgPSBheDI1LT5heDI1X2Rldi0+dmFsdWVzW0FYMjVfVkFMVUVTX1dJTkRPV107CgkJfSBlbHNlIHsKCQkJYXgyNS0+bW9kdWx1cyAgID0gQVgyNV9FTU9EVUxVUzsKCQkJYXgyNS0+d2luZG93ICAgID0gYXgyNS0+YXgyNV9kZXYtPnZhbHVlc1tBWDI1X1ZBTFVFU19FV0lORE9XXTsKCQl9CgkJYXgyNV9zZW5kX2NvbnRyb2woYXgyNSwgQVgyNV9VQSwgcGYsIEFYMjVfUkVTUE9OU0UpOwoJCWF4MjVfc3RvcF90MXRpbWVyKGF4MjUpOwoJCWF4MjVfc3RhcnRfdDN0aW1lcihheDI1KTsKCQlheDI1X3N0YXJ0X2lkbGV0aW1lcihheDI1KTsKCQlheDI1LT5jb25kaXRpb24gPSAweDAwOwoJCWF4MjUtPnZzICAgICAgICA9IDA7CgkJYXgyNS0+dmEgICAgICAgID0gMDsKCQlheDI1LT52ciAgICAgICAgPSAwOwoJCWF4MjVfcmVxdWV1ZV9mcmFtZXMoYXgyNSk7CgkJYXgyNV9kYW1hX29uKGF4MjUpOwoJCWJyZWFrOwoKCWNhc2UgQVgyNV9ESVNDOgoJCWF4MjVfc2VuZF9jb250cm9sKGF4MjUsIEFYMjVfVUEsIHBmLCBBWDI1X1JFU1BPTlNFKTsKCQlheDI1X2RhbWFfb2ZmKGF4MjUpOwoJCWF4MjVfZGlzY29ubmVjdChheDI1LCAwKTsKCQlicmVhazsKCgljYXNlIEFYMjVfRE06CgkJYXgyNV9kYW1hX29mZihheDI1KTsKCQlheDI1X2Rpc2Nvbm5lY3QoYXgyNSwgRUNPTk5SRVNFVCk7CgkJYnJlYWs7CgoJY2FzZSBBWDI1X1JSOgoJY2FzZSBBWDI1X1JOUjoKCQlpZiAoZnJhbWV0eXBlID09IEFYMjVfUlIpCgkJCWF4MjUtPmNvbmRpdGlvbiAmPSB+QVgyNV9DT05EX1BFRVJfUlhfQlVTWTsKCQllbHNlCgkJCWF4MjUtPmNvbmRpdGlvbiB8PSBBWDI1X0NPTkRfUEVFUl9SWF9CVVNZOwoKCQlpZiAoYXgyNV92YWxpZGF0ZV9ucihheDI1LCBucikpIHsKCQkJaWYgKGF4MjVfY2hlY2tfaWZyYW1lc19hY2tlZChheDI1LCBucikpCgkJCQlheDI1LT5uMmNvdW50PTA7CgkJCWlmICh0eXBlID09IEFYMjVfQ09NTUFORCAmJiBwZikKCQkJCWF4MjVfZHNfZW5xdWlyeV9yZXNwb25zZShheDI1KTsKCQl9IGVsc2UgewoJCQlheDI1X2RzX25yX2Vycm9yX3JlY292ZXJ5KGF4MjUpOwoJCQlheDI1LT5zdGF0ZSA9IEFYMjVfU1RBVEVfMTsKCQl9CgkJYnJlYWs7CgoJY2FzZSBBWDI1X1JFSjoKCQlheDI1LT5jb25kaXRpb24gJj0gfkFYMjVfQ09ORF9QRUVSX1JYX0JVU1k7CgoJCWlmIChheDI1X3ZhbGlkYXRlX25yKGF4MjUsIG5yKSkgewoJCQlpZiAoYXgyNS0+dmEgIT0gbnIpCgkJCQlheDI1LT5uMmNvdW50PTA7CgoJCQlheDI1X2ZyYW1lc19hY2tlZChheDI1LCBucik7CgkJCWF4MjVfY2FsY3VsYXRlX3J0dChheDI1KTsKCQkJYXgyNV9zdG9wX3QxdGltZXIoYXgyNSk7CgkJCWF4MjVfc3RhcnRfdDN0aW1lcihheDI1KTsKCQkJYXgyNV9yZXF1ZXVlX2ZyYW1lcyhheDI1KTsKCgkJCWlmICh0eXBlID09IEFYMjVfQ09NTUFORCAmJiBwZikKCQkJCWF4MjVfZHNfZW5xdWlyeV9yZXNwb25zZShheDI1KTsKCQl9IGVsc2UgewoJCQlheDI1X2RzX25yX2Vycm9yX3JlY292ZXJ5KGF4MjUpOwoJCQlheDI1LT5zdGF0ZSA9IEFYMjVfU1RBVEVfMTsKCQl9CgkJYnJlYWs7CgoJY2FzZSBBWDI1X0k6CgkJaWYgKCFheDI1X3ZhbGlkYXRlX25yKGF4MjUsIG5yKSkgewoJCQlheDI1X2RzX25yX2Vycm9yX3JlY292ZXJ5KGF4MjUpOwoJCQlheDI1LT5zdGF0ZSA9IEFYMjVfU1RBVEVfMTsKCQkJYnJlYWs7CgkJfQoJCWlmIChheDI1LT5jb25kaXRpb24gJiBBWDI1X0NPTkRfUEVFUl9SWF9CVVNZKSB7CgkJCWF4MjVfZnJhbWVzX2Fja2VkKGF4MjUsIG5yKTsKCQkJYXgyNS0+bjJjb3VudCA9IDA7CgkJfSBlbHNlIHsKCQkJaWYgKGF4MjVfY2hlY2tfaWZyYW1lc19hY2tlZChheDI1LCBucikpCgkJCQlheDI1LT5uMmNvdW50ID0gMDsKCQl9CgkJaWYgKGF4MjUtPmNvbmRpdGlvbiAmIEFYMjVfQ09ORF9PV05fUlhfQlVTWSkgewoJCQlpZiAocGYpIGF4MjVfZHNfZW5xdWlyeV9yZXNwb25zZShheDI1KTsKCQkJYnJlYWs7CgkJfQoJCWlmIChucyA9PSBheDI1LT52cikgewoJCQlheDI1LT52ciA9IChheDI1LT52ciArIDEpICUgYXgyNS0+bW9kdWx1czsKCQkJcXVldWVkID0gYXgyNV9yeF9pZnJhbWUoYXgyNSwgc2tiKTsKCQkJaWYgKGF4MjUtPmNvbmRpdGlvbiAmIEFYMjVfQ09ORF9PV05fUlhfQlVTWSkKCQkJCWF4MjUtPnZyID0gbnM7CS8qIGF4MjUtPnZyIC0gMSAqLwoJCQlheDI1LT5jb25kaXRpb24gJj0gfkFYMjVfQ09ORF9SRUpFQ1Q7CgkJCWlmIChwZikgewoJCQkJYXgyNV9kc19lbnF1aXJ5X3Jlc3BvbnNlKGF4MjUpOwoJCQl9IGVsc2UgewoJCQkJaWYgKCEoYXgyNS0+Y29uZGl0aW9uICYgQVgyNV9DT05EX0FDS19QRU5ESU5HKSkgewoJCQkJCWF4MjUtPmNvbmRpdGlvbiB8PSBBWDI1X0NPTkRfQUNLX1BFTkRJTkc7CgkJCQkJYXgyNV9zdGFydF90MnRpbWVyKGF4MjUpOwoJCQkJfQoJCQl9CgkJfSBlbHNlIHsKCQkJaWYgKGF4MjUtPmNvbmRpdGlvbiAmIEFYMjVfQ09ORF9SRUpFQ1QpIHsKCQkJCWlmIChwZikgYXgyNV9kc19lbnF1aXJ5X3Jlc3BvbnNlKGF4MjUpOwoJCQl9IGVsc2UgewoJCQkJYXgyNS0+Y29uZGl0aW9uIHw9IEFYMjVfQ09ORF9SRUpFQ1Q7CgkJCQlheDI1X2RzX2VucXVpcnlfcmVzcG9uc2UoYXgyNSk7CgkJCQlheDI1LT5jb25kaXRpb24gJj0gfkFYMjVfQ09ORF9BQ0tfUEVORElORzsKCQkJfQoJCX0KCQlicmVhazsKCgljYXNlIEFYMjVfRlJNUjoKCWNhc2UgQVgyNV9JTExFR0FMOgoJCWF4MjVfZHNfZXN0YWJsaXNoX2RhdGFfbGluayhheDI1KTsKCQlheDI1LT5zdGF0ZSA9IEFYMjVfU1RBVEVfMTsKCQlicmVhazsKCglkZWZhdWx0OgoJCWJyZWFrOwoJfQoKCXJldHVybiBxdWV1ZWQ7Cn0KCi8qCiAqCUhpZ2hlciBsZXZlbCB1cGNhbGwgZm9yIGEgTEFQQiBmcmFtZQogKi8KaW50IGF4MjVfZHNfZnJhbWVfaW4oYXgyNV9jYiAqYXgyNSwgc3RydWN0IHNrX2J1ZmYgKnNrYiwgaW50IHR5cGUpCnsKCWludCBxdWV1ZWQgPSAwLCBmcmFtZXR5cGUsIG5zLCBuciwgcGY7CgoJZnJhbWV0eXBlID0gYXgyNV9kZWNvZGUoYXgyNSwgc2tiLCAmbnMsICZuciwgJnBmKTsKCglzd2l0Y2ggKGF4MjUtPnN0YXRlKSB7CgljYXNlIEFYMjVfU1RBVEVfMToKCQlxdWV1ZWQgPSBheDI1X2RzX3N0YXRlMV9tYWNoaW5lKGF4MjUsIHNrYiwgZnJhbWV0eXBlLCBwZiwgdHlwZSk7CgkJYnJlYWs7CgljYXNlIEFYMjVfU1RBVEVfMjoKCQlxdWV1ZWQgPSBheDI1X2RzX3N0YXRlMl9tYWNoaW5lKGF4MjUsIHNrYiwgZnJhbWV0eXBlLCBwZiwgdHlwZSk7CgkJYnJlYWs7CgljYXNlIEFYMjVfU1RBVEVfMzoKCQlxdWV1ZWQgPSBheDI1X2RzX3N0YXRlM19tYWNoaW5lKGF4MjUsIHNrYiwgZnJhbWV0eXBlLCBucywgbnIsIHBmLCB0eXBlKTsKCQlicmVhazsKCX0KCglyZXR1cm4gcXVldWVkOwp9Cgo=