Autarch/web/static/js/lib/fastboot-bundle.js

4 lines
145 KiB
JavaScript
Raw Permalink Normal View History

var Fastboot=(()=>{var Yn=Object.defineProperty;var yr=Object.getOwnPropertyDescriptor;var kr=Object.getOwnPropertyNames;var Er=Object.prototype.hasOwnProperty;var Ar=(n,t)=>{for(var e in t)Yn(n,e,{get:t[e],enumerable:!0})},Sr=(n,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of kr(t))!Er.call(n,s)&&s!==e&&Yn(n,s,{get:()=>t[s],enumerable:!(a=yr(t,s))||a.enumerable});return n};var Ir=n=>Sr(Yn({},"__esModule",{value:!0}),n);var vo={};Ar(vo,{FastbootDevice:()=>Hn,setDebugLevel:()=>Na});var go={},fi;(function(n){n[n.Silent=0]="Silent",n[n.Debug=1]="Debug",n[n.Verbose=2]="Verbose"})(fi||(fi={}));var Ti=fi.Silent;function Oe(...n){Ti>=1&&console.log(...n)}function Bt(...n){Ti>=2&&console.log(...n)}function Na(n){Ti=n}function Rt(n){return new Promise((t,e)=>{let a=new FileReader;a.onload=()=>{t(a.result)},a.onerror=()=>{e(a.error)},a.readAsArrayBuffer(n)})}function Tr(){return new Promise((n,t)=>{window.requestAnimationFrame(n)})}async function an(n,t,e,a,s){let c=new Date().getTime(),u=!1;n(t,e,0);let v=(async()=>{let b,U=c+a;do b=new Date().getTime(),n(t,e,(b-c)/a),await Tr();while(!u&&b<U)})();await Promise.race([v,s]),u=!0,await v,await s,n(t,e,1)}var ui=class extends Error{constructor(t){super(`Timeout of ${t} ms exceeded`),this.name="TimeoutError",this.timeout=t}};function Ur(n,t){return new Promise((e,a)=>{let s=!1,c=setTimeout(()=>{s=!0,a(new ui(t))},t);n.then(u=>{s||e(u)}).catch(u=>{s||a(u)}).finally(()=>{s||clearTimeout(c)})})}var $a=3978755898,Ha=1,Pa=0,Mt=28,_t=12,Rr=64*1024*1024,Zt=class extends Error{constructor(t){super(t),this.name="ImageError"}},Kt;(function(n){n[n.Raw=51905]="Raw",n[n.Fill=51906]="Fill",n[n.Skip=51907]="Skip",n[n.Crc32=51908]="Crc32"})(Kt||(Kt={}));function qa(n){let t=new DataView(n);if(t.getUint32(0,!0)!==$a)return null;let a=t.getUint16(4,!0),s=t.getUint16(6,!0);if(a!==Ha||s<Pa)throw new Zt(`Unsupported sparse image version ${a}.${s}`);let c=t.getUint16(8,!0),u=t.getUint16(10,!0);if(c!==Mt||u!==_t)throw new Zt(`Invalid file header size ${c}, chunk header size ${u}`);let v=t.getUint32(12,!0);if(v%4!==0)throw new Zt(`Block size ${v} is not a multiple of 4`);return{blockSize:v,blocks:t.getUint32(16,!0),chunks:t.getUint32(20,!0),crc32:t.getUint32(24,!0)}}function Dr(n){let t=new DataView(n);return{type:t.getUint16(0,!0),blocks:t.getUint32(4,!0),dataBytes:t.getUint32(8,!0)-_t,data:null}}function Hi(n){return n.map(t=>t.blocks).reduce((t,e)=>t+e,0)}function Or(n){return n.map(t=>t.data.byteLength).reduce((t,e)=>t+e,0)}function Va(n){return Mt+_t*n.length+Or(n)}function _i(n,t){let e=new ArrayBuffer(Va(t)),a=new DataView(e),s=new Uint8Array(e);a.setUint32(0,$a,!0),a.setUint16(4,Ha,!0),a.setUint16(6,Pa,!0),a.setUint16(8,Mt,!0),a.setUint16(10,_t,!0),a.setUint32(12,n.blockSize,!0),a.setUint32(16,n.blocks,!0),a.setUint32(20,t.length,!0),a.setUint32(24,0,!0);let c=Mt;for(let u of t){a.setUint16(c,u.type,!0),a.setUint16(c+2,0,!0),a.setUint32(c+4,u.blocks,!0),a.setUint32(c+8,_t+u.data.byteLength,!0),c+=_t;let v=new Uint8Array(u.data);s.set(v,c),c+=u.data.byteLength}return e}function Cr(n){let t={blockSize:4096,blocks:n.byteLength/4096,chunks:1,crc32:0},e=[];for(;n.byteLength>0;){let a=Math.min(n.byteLength,Rr);e.push({type:Kt.Raw,blocks:a/t.blockSize,data:n.slice(0,a)}),n=n.slice(a)}return _i(t,e)}async function*Fr(n,t){if(Oe(`Splitting ${n.size}-byte sparse image into ${t}-byte chunks`),n.size<=t){Oe("Blob fits in 1 payload, not splitting"),yield{data:await Rt(n),bytes:n.size};return}let e=await Rt(n.slice(0,Mt)),a=qa(e);if(a===null)throw new Zt("Blob is not a sparse image");a.crc32=0,n=n.slice(Mt);let s=[],c=0;for(let u=0;u<a.chunks;u++){let v=await Rt(n.slice(0,_t)),b=Dr(v);b.data=await Rt(n.slice(_t,_t+b.dataBytes)),n=n.slice(_t+b.dataBytes);let U=t-Va(s);if(Bt(` Chunk ${u}: type ${b.type}, ${b.dataBytes} bytes / ${b.blocks} blocks, ${U} bytes remaining`),U>=b.dataBytes)Bt(" Space is available, adding chunk"),s.push(b),c+=b.blocks*a.blockSize;else{let E=Hi(s);s.push({type:Kt.Skip,blocks:a.blocks-E,data:new ArrayBuffer(0),dataBytes:0}),Bt(`Partition is ${a.blocks} blocks, used
`)){let a=e.match(/^require\s+(.+?)=(.+)$/);if(!a)continue;let s=a[1];s==="board"&&(s="product");let c=a[2],u=c.split("|");if(s==="partition-exists"){let v=await n.getVariable(`has-slot:${c}`);if(v!=="yes"&&v!=="no")throw new ut("FAIL",`Requirement ${s}=${c} failed, device lacks partition`);if(!mr.includes(c)&&!br.includes(c))throw new ut("FAIL",`Requirement ${s}=${c} failed, unrecognized partition`)}else{let v=await n.getVariable(s);if(u.includes(v))Oe(`Requirement ${s}=${c} passed`);else{let b=`Requirement ${s}=${c} failed, value = ${v}`;throw Oe(b),new ut("FAIL",b)}}}}async function Ma(n,t,e){try{await n.reboot(t,!1)}catch{}await n.waitForConnect(e)}async function _o(n,t,e,a,s=(c,u,v)=>{}){s("load","package",0);let u=await new $n(new Nn(t)).getEntries();await n.getVariable("is-userspace")==="yes"&&await n.reboot("bootloader",!0,a),await Rn(n,u,s,["bootloader"]),await an(s,"reboot","device",di,Ma(n,"bootloader",a)),await Rn(n,u,s,["radio"]),await an(s,"reboot","device",di,Ma(n,"bootloader",a));let v=await n.getVariable("snapshot-update-status");v!==null&&v!=="none"&&await n.runCommand("snapshot-update:cancel"),Oe("Loading nested images from zip"),s("unpack","images",0);let b=u.find(O=>O.filename.match(/image-.+\.zip$/)),U=await Fn(b,new pn("application/zip"),{onprogress:(O,Y)=>{s("unpack","images",O/Y)}}),D=await new $n(new Nn(U)).getEntries();if(b=D.find(O=>O.filename==="android-info.txt"),b!==void 0){let O=await Fn(b,new bi);await uo(n,O)}if(await Rn(n,D,s,mr),b=D.find(O=>O.filename==="super_empty.img"),b!==void 0){await an(s,"reboot","device",co,n.reboot("fastboot",!0,a));let O=await n.getVariable("super-partition-name");O||(O="super");let Y=e?"wipe":"flash";s(Y,"super",0);let ae=await Fn(b,new pn("application/octet-stream"));await n.upload(O,await Rt(ae),y=>{s(Y,"super",y)}),await n.runCommand(`update-super:${O}${e?":wipe":""}`)}await Rn(n,D,s,br),await n.getVariable("is-userspace")==="yes"&&await an(s,"reboot","device",di,n.reboot("bootloader",!0,a)),b=u.find(O=>O.filename.endsWith("avb_pkmd.bin")),b!==void 0&&(await n.runCommand("erase:avb_custom_key"),await wr(n,b,s,"avb_custom_key")),e&&await an(s,"wipe","data",fo,n.runCommand("erase:userdata"))}var po=255,xo=66,ho=3,ja=16384,mo=512*1024*1024,bo=1024*1024*1024,wo=1e4,Lt=class extends Error{constructor(t){super(t),this.name="UsbError"}},ut=class extends Error{constructor(t,e){super(`Bootloader replied with ${t}: ${e}`),this.status=t,this.bootloaderMessage=e,this.name="FastbootError"}},Hn=class{constructor(){this.device=null,this.epIn=null,this.epOut=null,this._registeredUsbListeners=!1,this._connectResolve=null,this._connectReject=null,this._disconnectResolve=null}get isConnected(){return this.device!==null&&this.device.opened&&this.device.configurations[0].interfaces[0].claimed}async _validateAndConnectDevice(){if(this.device===null)throw new Lt("Attempted to connect to null device");let t=this.device.configurations[0].interfaces[0].alternates[0];if(t.endpoints.length!==2)throw new Lt("Interface has wrong number of endpoints");this.epIn=null,this.epOut=null;for(let e of t.endpoints){if(Bt("Checking endpoint:",e),e.type!=="bulk")throw new Lt("Interface endpoint is not bulk");if(e.direction==="in")if(this.epIn===null)this.epIn=e.endpointNumber;else throw new Lt("Interface has multiple IN endpoints");else if(e.direction==="out")if(this.epOut===null)this.epOut=e.endpointNumber;else throw new Lt("Interface has multiple OUT endpoints")}Bt("Endpoints: in =",this.epIn,", out =",this.epOut);try{await this.device.open();try{await this.device.reset()}catch{}await this.device.selectConfiguration(1),await this.device.claimInterface(0)}catch(e){throw this._connectReject!==null&&(this._connectReject(e),this._connectResolve=null,this._connectReject=null),e}this._connectResolve!==null&&(this._connectResolve(void 0),this._connectResolve=null,this._connectReject=null)}async waitForDisconnect(){if(this.device!==null)return await new Promise((t,e)=>{this._disconnectResolve=t})}async waitForConnect(t=()=>{}){return navigator.userAgent.includes("Android")&&(await this.waitForDisconn
`;else if(e==="DATA")t.dataSize=c;else throw new ut(e,c)}while(e==="INFO");return t}async runCommand(t){if(t.length>64)throw new RangeError;let e=new TextEncoder().encode(t);return await this.device.transferOut(this.epOut,e),Oe("Command:",t),this._readResponse()}async getVariable(t){let e;try{e=(await Ur(this.runCommand(`getvar:${t}`),wo)).text}catch(a){if(a instanceof ut&&a.status=="FAIL")e=null;else throw a}return e?e.trim():null}async _getDownloadSize(){try{let t=(await this.getVariable("max-download-size")).toLowerCase();if(t)return Math.min(parseInt(t,16),bo)}catch{}return mo}async _sendRawPayload(t,e){let a=0,s=t.byteLength;for(;s>0;){let c=t.slice(a*ja,(a+1)*ja);a%1e3===0&&Bt(` Sending ${c.byteLength} bytes to endpoint, ${s} remaining, i=${a}`),a%10===0&&e((t.byteLength-s)/t.byteLength),await this.device.transferOut(this.epOut,c),s-=c.byteLength,a+=1}e(1)}async upload(t,e,a=s=>{}){Oe(`Uploading single sparse to ${t}: ${e.byteLength} bytes`);let s=e.byteLength.toString(16).padStart(8,"0");if(s.length!==8)throw new ut("FAIL",`Transfer size overflow: ${s} is more than 8 digits`);let c=await this.runCommand(`download:${s}`);if(c.dataSize===void 0)throw new ut("FAIL",`Unexpected response to download command: ${c.text}`);if(parseInt(c.dataSize,16)!==e.byteLength)throw new ut("FAIL",`Bootloader wants ${e.byteLength} bytes, requested to send ${e.byteLength} bytes`);Oe(`Sending payload: ${e.byteLength} bytes`),await this._sendRawPayload(e,a),Oe("Payload sent, waiting for response..."),await this._readResponse()}async reboot(t="",e=!1,a=()=>{}){t.length>0?await this.runCommand(`reboot-${t}`):await this.runCommand("reboot"),e&&await this.waitForConnect(a)}async flashBlob(t,e,a=s=>{}){await this.getVariable(`has-slot:${t}`)==="yes"&&(t+="_"+await this.getVariable("current-slot"));let s=await this._getDownloadSize(),c=await Rt(e.slice(0,Mt)),u=e.size,v=!1;try{let E=qa(c);E!==null&&(u=E.blocks*E.blockSize,v=!0)}catch{}if(await this.getVariable(`is-logical:${t}`)==="yes"&&(await this.runCommand(`resize-logical-partition:${t}:0`),await this.runCommand(`resize-logical-partition:${t}:${u}`)),e.size>s&&!v){Oe(`${t} image is raw, converting to sparse`);let E=await Rt(e),D=Cr(E);e=new Blob([D])}Oe(`Flashing ${e.size} bytes to ${t}, ${s} bytes per split`);let b=0,U=0;for await(let E of Fr(e,s))await this.upload(t,E.data,D=>{a((U+D*E.bytes)/u)}),Oe("Flashing payload..."),await this.runCommand(`flash:${t}`),b+=1,U+=E.bytes;Oe(`Flashed ${t} with ${b} split(s)`)}async bootBlob(t,e=a=>{}){Oe(`Booting ${t.size} bytes image`);let a=await Rt(t);await this.upload("boot.img",a,e),Oe("Booting payload..."),await this.runCommand("boot"),Oe(`Booted ${t.size} bytes image`)}async flashFactoryZip(t,e,a,s=c=>{}){return await _o(this,t,e,a,s)}};return Ir(vo);})();