LyoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogICAgIHBhc3N0aHJvdWdoLmMgLS0gRW11MTBrMSBkaWdpdGFsIHBhc3N0aHJvdWdoCiAqICAgICBDb3B5cmlnaHQgKEMpIDIwMDEgIEp1aGEgWXJq9mzkIDxqeXJqb2xhQGNjLmh1dC5maT4KICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICoKICogICAgIERhdGUgICAgICAgICAgICAgICAgIEF1dGhvciAgICAgICAgICBTdW1tYXJ5IG9mIGNoYW5nZXMKICogICAgIC0tLS0gICAgICAgICAgICAgICAgIC0tLS0tLSAgICAgICAgICAtLS0tLS0tLS0tLS0tLS0tLS0KICogICAgIE1heSAxNSwgMjAwMQkgICAgSnVoYSBZcmr2bOQJICAgIGJhc2UgY29kZSByZWxlYXNlCiAqCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqCiAqICAgICBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqICAgICBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcwogKiAgICAgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YKICogICAgIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiAgICAgVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqICAgICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgogKiAgICAgTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQogKiAgICAgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYwogKiAgICAgTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZQogKiAgICAgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLiwgNjc1IE1hc3MgQXZlLCBDYW1icmlkZ2UsIE1BIDAyMTM5LAogKiAgICAgVVNBLgogKgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKi8KICAgICAgICAgICAgICAgICAgICAgICAKI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgojaW5jbHVkZSA8bGludXgvcG9sbC5oPgojaW5jbHVkZSA8bGludXgvc2xhYi5oPgojaW5jbHVkZSA8bGludXgvYml0b3BzLmg+CiNpbmNsdWRlIDxhc20vaW8uaD4KI2luY2x1ZGUgPGxpbnV4L3NjaGVkLmg+CiNpbmNsdWRlIDxsaW51eC9zbXBfbG9jay5oPgoKI2luY2x1ZGUgImh3YWNjZXNzLmgiCiNpbmNsdWRlICJjYXJkd28uaCIKI2luY2x1ZGUgImNhcmR3aS5oIgojaW5jbHVkZSAicmVjbWdyLmgiCiNpbmNsdWRlICJpcnFtZ3IuaCIKI2luY2x1ZGUgImF1ZGlvLmgiCiNpbmNsdWRlICI4MDEwLmgiCgpzdGF0aWMgdm9pZCBwdF9wdXRzYW1wbGVzKHN0cnVjdCBwdF9kYXRhICpwdCwgdTE2ICpwdHIsIHUxNiBsZWZ0LCB1MTYgcmlnaHQpCnsKCXVuc2lnbmVkIGludCBpZHg7CgoJcHRyW3B0LT5jb3B5cHRyXSA9IGxlZnQ7CglpZHggPSBwdC0+Y29weXB0ciArIFBUX1NBTVBMRVMvMjsKCWlkeCAlPSBQVF9TQU1QTEVTOwoJcHRyW2lkeF0gPSByaWdodDsKfQoKc3RhdGljIGlubGluZSBpbnQgcHRfY2FuX3dyaXRlKHN0cnVjdCBwdF9kYXRhICpwdCkKewoJcmV0dXJuIHB0LT5ibG9ja3NfY29waWVkIDwgcHQtPmJsb2Nrc19wbGF5ZWQgKyA4Owp9CgpzdGF0aWMgaW50IHB0X3dhaXRfZm9yX3dyaXRlKHN0cnVjdCBlbXUxMGsxX3dhdmVkZXZpY2UgKndhdmVkZXYsIGludCBub25ibG9jaykKewoJc3RydWN0IGVtdTEwazFfY2FyZCAqY2FyZCA9IHdhdmVkZXYtPmNhcmQ7CglzdHJ1Y3QgcHRfZGF0YSAqcHQgPSAmY2FyZC0+cHQ7CgoJaWYgKG5vbmJsb2NrICYmICFwdF9jYW5fd3JpdGUocHQpKQoJCXJldHVybiAtRUFHQUlOOwoJd2hpbGUgKCFwdF9jYW5fd3JpdGUocHQpICYmIHB0LT5zdGF0ZSAhPSBQVF9TVEFURV9JTkFDVElWRSkgewoJCWludGVycnVwdGlibGVfc2xlZXBfb24oJnB0LT53YWl0KTsKCQlpZiAoc2lnbmFsX3BlbmRpbmcoY3VycmVudCkpCgkJCXJldHVybiAtRVJFU1RBUlRTWVM7Cgl9CglpZiAocHQtPnN0YXRlID09IFBUX1NUQVRFX0lOQUNUSVZFKQoJCXJldHVybiAtRUFHQUlOOwoJCglyZXR1cm4gMDsKfQoKc3RhdGljIGludCBwdF9wdXRibG9jayhzdHJ1Y3QgZW11MTBrMV93YXZlZGV2aWNlICp3YXZlX2RldiwgdTE2ICpibG9jaywgaW50IG5vbmJsb2NrKQp7CglzdHJ1Y3Qgd29pbnN0ICp3b2luc3QgPSB3YXZlX2Rldi0+d29pbnN0OwoJc3RydWN0IGVtdTEwazFfY2FyZCAqY2FyZCA9IHdhdmVfZGV2LT5jYXJkOwoJc3RydWN0IHB0X2RhdGEgKnB0ID0gJmNhcmQtPnB0OwoJdTE2ICpwdHIgPSAodTE2ICopIGNhcmQtPnRhbmttZW0uYWRkcjsKCWludCBpID0gMCwgcjsKCXVuc2lnbmVkIGxvbmcgZmxhZ3M7CgoJciA9IHB0X3dhaXRfZm9yX3dyaXRlKHdhdmVfZGV2LCBub25ibG9jayk7CglpZiAociA8IDApCgkJcmV0dXJuIHI7CglzcGluX2xvY2tfaXJxc2F2ZSgmY2FyZC0+cHQubG9jaywgZmxhZ3MpOwoJd2hpbGUgKGkgPCBQVF9CTE9DS1NBTVBMRVMpIHsKCQlwdF9wdXRzYW1wbGVzKHB0LCBwdHIsIGJsb2NrWzIqaV0sIGJsb2NrWzIqaSsxXSk7CgkJaWYgKHB0LT5jb3B5cHRyID09IDApCgkJCXB0LT5jb3B5cHRyID0gUFRfU0FNUExFUzsKCQlwdC0+Y29weXB0ci0tOwoJCWkrKzsKCX0KCXdvaW5zdC0+dG90YWxfY29waWVkICs9IFBUX0JMT0NLU0laRTsKCXB0LT5ibG9ja3NfY29waWVkKys7CglpZiAocHQtPmJsb2Nrc19jb3BpZWQgPj0gNCAmJiBwdC0+c3RhdGUgIT0gUFRfU1RBVEVfUExBWUlORykgewoJCURQRigyLCAiYWN0aXZhdGluZyBkaWdpdGFsIHBhc3MtdGhyb3VnaCBwbGF5YmFja1xuIik7CgkJc2JsaXZlX3dyaXRlcHRyKGNhcmQsIEdQUl9CQVNFICsgcHQtPmVuYWJsZV9ncHIsIDAsIDEpOwoJCXB0LT5zdGF0ZSA9IFBUX1NUQVRFX1BMQVlJTkc7Cgl9CglzcGluX3VubG9ja19pcnFyZXN0b3JlKCZjYXJkLT5wdC5sb2NrLCBmbGFncyk7CglyZXR1cm4gMDsKfQoKaW50IGVtdTEwazFfcHRfc2V0dXAoc3RydWN0IGVtdTEwazFfd2F2ZWRldmljZSAqd2F2ZV9kZXYpCnsKCXUzMiBiaXRzOwoJc3RydWN0IGVtdTEwazFfY2FyZCAqY2FyZCA9IHdhdmVfZGV2LT5jYXJkOwoJc3RydWN0IHB0X2RhdGEgKnB0ID0gJmNhcmQtPnB0OwoJaW50IGk7CgoJZm9yIChpID0gMDsgaSA8IDM7IGkrKykgewoJCXB0LT5vbGRfc3Bjc1tpXSA9IHNibGl2ZV9yZWFkcHRyKGNhcmQsIFNQQ1MwICsgaSwgMCk7CgkJaWYgKHB0LT5zcGNzX3RvX3VzZSAmICgxIDw8IGkpKSB7CgkJCURQRCgyLCAidXNpbmcgUy9QRElGIHBvcnQgJWRcbiIsIGkpOwoJCQliaXRzID0gU1BDU19DTEtBQ0NZXzEwMDBQUE0gfCBTUENTX1NBTVBMRVJBVEVfNDggfAoJCQkJU1BDU19DSEFOTkVMTlVNX0xFRlQgfCBTUENTX1NPVVJDRU5VTV9VTlNQRUMgfCBTUENTX0dFTkVSQVRJT05TVEFUVVMgfAoJCQkJMHgwMDAwMTIwMCB8IFNQQ1NfRU1QSEFTSVNfTk9ORSB8IFNQQ1NfQ09QWVJJR0hUOwoJCQlpZiAocHQtPmFjM2RhdGEpCgkJCQliaXRzIHw9IFNQQ1NfTk9UQVVESU9EQVRBOwoJCQlzYmxpdmVfd3JpdGVwdHIoY2FyZCwgU1BDUzAgKyBpLCAwLCBiaXRzKTsKCQl9Cgl9CglyZXR1cm4gMDsKfQoKc3NpemVfdCBlbXUxMGsxX3B0X3dyaXRlKHN0cnVjdCBmaWxlICpmaWxlLCBjb25zdCBjaGFyIF9fdXNlciAqYnVmZmVyLCBzaXplX3QgY291bnQpCnsKCXN0cnVjdCBlbXUxMGsxX3dhdmVkZXZpY2UgKndhdmVfZGV2ID0gKHN0cnVjdCBlbXUxMGsxX3dhdmVkZXZpY2UgKikgZmlsZS0+cHJpdmF0ZV9kYXRhOwoJc3RydWN0IGVtdTEwazFfY2FyZCAqY2FyZCA9IHdhdmVfZGV2LT5jYXJkOwoJc3RydWN0IHB0X2RhdGEgKnB0ID0gJmNhcmQtPnB0OwoJaW50IG5vbmJsb2NrLCBpLCByLCBibG9ja3MsIGJsb2Nrc19jb3BpZWQsIGJ5dGVzX2NvcGllZCA9IDA7CgoJRFBEKDMsICJlbXUxMGsxX3B0X3dyaXRlKCk6ICVkIGJ5dGVzXG4iLCBjb3VudCk7CgkKCW5vbmJsb2NrID0gZmlsZS0+Zl9mbGFncyAmIE9fTk9OQkxPQ0s7CgkKCWlmIChjYXJkLT50YW5rbWVtLnNpemUgPCBQVF9TQU1QTEVTKjIpCgkJcmV0dXJuIC1FRkFVTFQ7CglpZiAocHQtPnN0YXRlID09IFBUX1NUQVRFX0lOQUNUSVZFKSB7CgkJRFBGKDIsICJidWZwdHIgaW5pdFxuIik7CgkJcHQtPnBsYXlwdHIgPSBQVF9TQU1QTEVTLTE7CgkJcHQtPmNvcHlwdHIgPSBQVF9JTklUUFRSOwoJCXB0LT5ibG9ja3NfcGxheWVkID0gcHQtPmJsb2Nrc19jb3BpZWQgPSAwOwoJCW1lbXNldChjYXJkLT50YW5rbWVtLmFkZHIsIDAsIGNhcmQtPnRhbmttZW0uc2l6ZSk7CgkJcHQtPnN0YXRlID0gUFRfU1RBVEVfQUNUSVZBVEVEOwoJCXB0LT5idWYgPSBrbWFsbG9jKFBUX0JMT0NLU0laRSwgR0ZQX0tFUk5FTCk7CgkJcHQtPnByZXBlbmRfc2l6ZSA9IDA7CgkJaWYgKHB0LT5idWYgPT0gTlVMTCkKCQkJcmV0dXJuIC1FTk9NRU07CgkJZW11MTBrMV9wdF9zZXR1cCh3YXZlX2Rldik7Cgl9CglpZiAocHQtPnByZXBlbmRfc2l6ZSkgewoJCWludCBuZWVkZWQgPSBQVF9CTE9DS1NJWkUgLSBwdC0+cHJlcGVuZF9zaXplOwoKCQlEUEQoMywgInByZXBlbmQgc2l6ZSAlZCwgcHJlcGVuZGluZyAlZCBieXRlc1xuIiwgcHQtPnByZXBlbmRfc2l6ZSwgbmVlZGVkKTsKCQlpZiAoY291bnQgPCBuZWVkZWQpIHsKCQkJY29weV9mcm9tX3VzZXIocHQtPmJ1ZiArIHB0LT5wcmVwZW5kX3NpemUsIGJ1ZmZlciwgY291bnQpOwoJCQlwdC0+cHJlcGVuZF9zaXplICs9IGNvdW50OwoJCQlEUEQoMywgInByZXBlbmQgc2l6ZSBub3cgJWRcbiIsIHB0LT5wcmVwZW5kX3NpemUpOwoJCQlyZXR1cm4gY291bnQ7CgkJfQoJCWNvcHlfZnJvbV91c2VyKHB0LT5idWYgKyBwdC0+cHJlcGVuZF9zaXplLCBidWZmZXIsIG5lZWRlZCk7CgkJciA9IHB0X3B1dGJsb2NrKHdhdmVfZGV2LCAodTE2ICopIHB0LT5idWYsIG5vbmJsb2NrKTsKCQlpZiAocikKCQkJcmV0dXJuIHI7CgkJYnl0ZXNfY29waWVkICs9IG5lZWRlZDsKCQlwdC0+cHJlcGVuZF9zaXplID0gMDsKCX0KCWJsb2NrcyA9IChjb3VudC1ieXRlc19jb3BpZWQpL1BUX0JMT0NLU0laRTsKCWJsb2Nrc19jb3BpZWQgPSAwOwoJd2hpbGUgKGJsb2NrcyA+IDApIHsKCQl1MTYgX191c2VyICpidWZwdHIgPSAodTE2IF9fdXNlciAqKSBidWZmZXIgKyAoYnl0ZXNfY29waWVkLzIpOwoJCWNvcHlfZnJvbV91c2VyKHB0LT5idWYsIGJ1ZnB0ciwgUFRfQkxPQ0tTSVpFKTsKCQlyID0gcHRfcHV0YmxvY2sod2F2ZV9kZXYsICh1MTYgKilwdC0+YnVmLCBub25ibG9jayk7CgkJaWYgKHIpIHsKCQkJaWYgKGJ5dGVzX2NvcGllZCkKCQkJCXJldHVybiBieXRlc19jb3BpZWQ7CgkJCWVsc2UKCQkJCXJldHVybiByOwoJCX0KCQlieXRlc19jb3BpZWQgKz0gUFRfQkxPQ0tTSVpFOwoJCWJsb2Nrcy0tOwoJCWJsb2Nrc19jb3BpZWQrKzsKCX0KCWkgPSBjb3VudCAtIGJ5dGVzX2NvcGllZDsKCWlmIChpKSB7CgkJcHQtPnByZXBlbmRfc2l6ZSA9IGk7CgkJY29weV9mcm9tX3VzZXIocHQtPmJ1ZiwgYnVmZmVyICsgYnl0ZXNfY29waWVkLCBpKTsKCQlieXRlc19jb3BpZWQgKz0gaTsKCQlEUEQoMywgImZpbGxpbmcgcHJlcGVuZCBidWZmZXIgd2l0aCAlZCBieXRlcyIsIGkpOwoJfQoJcmV0dXJuIGJ5dGVzX2NvcGllZDsKfQoKdm9pZCBlbXUxMGsxX3B0X3N0b3Aoc3RydWN0IGVtdTEwazFfY2FyZCAqY2FyZCkKewoJc3RydWN0IHB0X2RhdGEgKnB0ID0gJmNhcmQtPnB0OwoJaW50IGk7CgoJaWYgKHB0LT5zdGF0ZSAhPSBQVF9TVEFURV9JTkFDVElWRSkgewoJCURQRigyLCAiZGlnaXRhbCBwYXNzLXRocm91Z2ggc3RvcHBlZFxuIik7CgkJc2JsaXZlX3dyaXRlcHRyKGNhcmQsIChjYXJkLT5pc19hdWRpZ3kgPyBBX0dQUl9CQVNFIDogR1BSX0JBU0UpICsgcHQtPmVuYWJsZV9ncHIsIDAsIDApOwoJCWZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHB0LT5zcGNzX3RvX3VzZSAmICgxIDw8IGkpKQoJCQkJc2JsaXZlX3dyaXRlcHRyKGNhcmQsIFNQQ1MwICsgaSwgMCwgcHQtPm9sZF9zcGNzW2ldKTsKCQl9CgkJcHQtPnN0YXRlID0gUFRfU1RBVEVfSU5BQ1RJVkU7CgkJaWYocHQtPmJ1ZikKCQkJa2ZyZWUocHQtPmJ1Zik7Cgl9Cn0KCnZvaWQgZW11MTBrMV9wdF93YXZlb3V0X3VwZGF0ZShzdHJ1Y3QgZW11MTBrMV93YXZlZGV2aWNlICp3YXZlX2RldikKewoJc3RydWN0IHdvaW5zdCAqd29pbnN0ID0gd2F2ZV9kZXYtPndvaW5zdDsKCXN0cnVjdCBwdF9kYXRhICpwdCA9ICZ3YXZlX2Rldi0+Y2FyZC0+cHQ7Cgl1MzIgcG9zOwoKCWlmIChwdC0+c3RhdGUgPT0gUFRfU1RBVEVfUExBWUlORyAmJiBwdC0+cG9zX2dwciA+PSAwKSB7CgkJcG9zID0gc2JsaXZlX3JlYWRwdHIod2F2ZV9kZXYtPmNhcmQsIEdQUl9CQVNFICsgcHQtPnBvc19ncHIsIDApOwoJCWlmIChwb3MgPiBQVF9CTE9DS1NBTVBMRVMpCgkJCXBvcyA9IFBUX0JMT0NLU0FNUExFUzsKCQlwb3MgPSA0ICogKFBUX0JMT0NLU0FNUExFUyAtIHBvcyk7Cgl9IGVsc2UKCQlwb3MgPSAwOwoJd29pbnN0LT50b3RhbF9wbGF5ZWQgPSBwdC0+YmxvY2tzX3BsYXllZCAqIHdvaW5zdC0+YnVmZmVyLmZyYWdtZW50X3NpemUgKyBwb3M7Cgl3b2luc3QtPmJ1ZmZlci5od19wb3MgPSBwb3M7Cn0K