Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transfer to QDL #33

Merged
merged 114 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
b2704d2
connect qualcomusb
bongbui321 Feb 8, 2024
5fea12a
finish read write
bongbui321 Feb 10, 2024
4e874ce
sahara setup
bongbui321 Feb 11, 2024
210a359
js is painful
bongbui321 Feb 12, 2024
51b64fc
finish sahara
bongbui321 Feb 14, 2024
e19ca3c
upload programmer
bongbui321 Feb 16, 2024
2a745eb
fix usblib
bongbui321 Feb 16, 2024
0ea835f
load programmer
bongbui321 Feb 17, 2024
9951603
time out
bongbui321 Feb 18, 2024
78746e6
can reset
bongbui321 Feb 19, 2024
ee16764
firehose detect partition storage info gpt
bongbui321 Feb 21, 2024
db7c273
can detect partition
bongbui321 Feb 22, 2024
9b6da71
can write
bongbui321 Feb 22, 2024
7926560
can erase
bongbui321 Feb 25, 2024
074a66d
can get active slot - haven't tested
bongbui321 Feb 25, 2024
ad5b519
setactive slot
bongbui321 Feb 25, 2024
c5c7225
remove releaseinterface
bongbui321 Feb 25, 2024
fedf8df
cleanup
bongbui321 Feb 25, 2024
ed15a11
add sparse
bongbui321 Feb 26, 2024
c6f960d
big cleanup
bongbui321 Feb 26, 2024
2d67a92
cleanup saharadefs
bongbui321 Feb 26, 2024
5a084fd
automate usb packet maxsize
bongbui321 Feb 26, 2024
097a33d
fix getactiveslot
bongbui321 Feb 27, 2024
1f9362e
import only used from gpt.js
bongbui321 Feb 27, 2024
527ab41
refactor
bongbui321 Feb 27, 2024
d30222b
move folder
bongbui321 Feb 27, 2024
b786d9e
integrate
bongbui321 Feb 28, 2024
6fa5db4
maxlun = 6
bongbui321 Feb 28, 2024
6c705ae
refactor
bongbui321 Feb 28, 2024
64ae7d4
serial
bongbui321 Feb 28, 2024
2609cc9
trailing white space
bongbui321 Feb 29, 2024
4e94310
fix getactiveslot
bongbui321 Feb 29, 2024
18ca751
auto download loader
bongbui321 Mar 1, 2024
947374a
setactiveslot
bongbui321 Mar 13, 2024
59ea980
transferout with retry
bongbui321 Mar 14, 2024
1d33e5d
add reset userdata
bongbui321 Mar 14, 2024
c3986eb
add semicolon
bongbui321 Mar 14, 2024
a71b4bd
update onprogress
bongbui321 Mar 14, 2024
78cc38a
test
bongbui321 Mar 14, 2024
7f2ca36
qdl update
bongbui321 Mar 14, 2024
7987cfb
fix sparse
bongbui321 Mar 15, 2024
d7eb916
works
bongbui321 Mar 15, 2024
fd90954
add loader
bongbui321 Mar 15, 2024
d5edde8
unpack system
bongbui321 Mar 15, 2024
8fe1e0e
remove sleep at write
bongbui321 Mar 16, 2024
7b87489
test
bongbui321 Mar 16, 2024
37ade70
update instructions
bongbui321 Mar 16, 2024
8491998
update instructions
bongbui321 Mar 16, 2024
5b1c91a
update instructions
bongbui321 Mar 16, 2024
9b3c025
move detach
bongbui321 Mar 16, 2024
bf53ae9
cleanup sahara
bongbui321 Mar 16, 2024
6100388
update scripts
bongbui321 Mar 16, 2024
8a05f6a
update instructions
bongbui321 Mar 16, 2024
9ad797e
update error message
bongbui321 Mar 16, 2024
c4067d1
fasttt
bongbui321 Mar 17, 2024
0972bfb
remove run()
bongbui321 Mar 17, 2024
ecca939
update eraseuserdata
bongbui321 Mar 17, 2024
663954f
auto upload loader
bongbui321 Mar 19, 2024
3f3689e
throw when disconnect + resetuserdata
bongbui321 Mar 20, 2024
db182ca
delete fb
bongbui321 Mar 20, 2024
bcd07fb
cleanup + catch disconnect
bongbui321 Mar 20, 2024
de264ab
update instruction
bongbui321 Mar 20, 2024
6acfcb5
faster
bongbui321 Mar 20, 2024
d20d6f2
fix
bongbui321 Mar 20, 2024
2286663
zadig_form update
andiradulescu Mar 20, 2024
8fde123
zadig_create_new_device update to match tint
andiradulescu Mar 20, 2024
a88caf4
update instruction
bongbui321 Mar 20, 2024
5da0ab1
Merge pull request #1 from andiradulescu/zadig_form
bongbui321 Mar 21, 2024
f73d372
remove
bongbui321 Mar 21, 2024
50a7843
good commit
bongbui321 Mar 21, 2024
2d9b0b9
update instruction
bongbui321 Mar 21, 2024
ae50ba8
timed out connect
bongbui321 Mar 21, 2024
791900a
increase timeout
bongbui321 Mar 21, 2024
c16d2eb
update instruction
bongbui321 Mar 21, 2024
d346736
update instruction + update detach script
bongbui321 Mar 21, 2024
2b4088f
add copy button
bongbui321 Mar 21, 2024
4db5f8b
log setactive successfully
bongbui321 Mar 22, 2024
af7089b
throw during connecting if error
bongbui321 Mar 23, 2024
00a0aa4
error diconnect while connecting
bongbui321 Mar 23, 2024
5f37d78
update throw error
bongbui321 Mar 23, 2024
16be08f
cleanup
bongbui321 Mar 23, 2024
de5b04c
cleanup
bongbui321 Mar 23, 2024
0bbb096
cleanup
bongbui321 Mar 23, 2024
03ee333
restructure + cleanup
bongbui321 Mar 24, 2024
7b7b4af
fix
bongbui321 Mar 24, 2024
3cace3a
fix style
bongbui321 Mar 24, 2024
f639765
style
bongbui321 Mar 24, 2024
f68971e
fix
bongbui321 Mar 24, 2024
4bba447
fix
bongbui321 Mar 24, 2024
3148ed1
serial -> int
bongbui321 Mar 24, 2024
92619dd
cleanup restructure
bongbui321 Mar 27, 2024
5c9b220
cleanup
bongbui321 Mar 27, 2024
5b1842e
cleanup sparse
bongbui321 Mar 28, 2024
e16579d
cleanup sparse
bongbui321 Mar 28, 2024
4ff2384
change name bytes to num
bongbui321 Mar 28, 2024
c4790e3
clean up path
bongbui321 Mar 28, 2024
5f76d4b
consistent var name cmd erase
bongbui321 Mar 28, 2024
966c81f
cleanup sparse
bongbui321 Mar 28, 2024
93a58fd
write resetuserdata
bongbui321 Mar 29, 2024
e9bf95f
remove erase cmd
bongbui321 Mar 30, 2024
0b56143
cleanup sparse
bongbui321 Mar 31, 2024
efa252c
update
bongbui321 Apr 3, 2024
1c4896c
update
bongbui321 Apr 3, 2024
0d917a5
cleanup style
bongbui321 Apr 4, 2024
9568cf5
clearer instruction
bongbui321 Apr 4, 2024
d7daad7
cleanup
bongbui321 Apr 4, 2024
16525e8
update check gpt header consistency
bongbui321 Apr 6, 2024
48cdc92
faster setactiveslot
bongbui321 Apr 6, 2024
713c1ae
move loader into Loaders
bongbui321 Apr 6, 2024
d40c9ce
4x faster setactiveslot
bongbui321 Apr 10, 2024
01cdc17
cleanup
bongbui321 Apr 17, 2024
e5286ce
remove web fastboot
bongbui321 Apr 17, 2024
07d904a
revert manifest test and image workers
bongbui321 Apr 17, 2024
334aa10
fix downloadLoader
bongbui321 Apr 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
"node": ">=18.0.0"
},
"dependencies": {
"android-fastboot": "github:commaai/fastboot.js#c3ec6fe3c96a48dab46e23d0c8c861af15b2144a",
"autoprefixer": "10.4.14",
"comlink": "^4.4.1",
"crc-32": "^1.2.2",
"eslint": "8.40.0",
"eslint-config-next": "13.4.1",
"jssha": "^3.3.1",
Expand Down
30 changes: 9 additions & 21 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

289 changes: 289 additions & 0 deletions src/QDL/firehose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
import { xmlParser } from "./xmlParser"
import { concatUint8Array, containsBytes, compareStringToBytes, sleep, readBlobAsBuffer } from "./utils"
import * as Sparse from "./sparse";


class response {
constructor(resp=false, data=new Uint8Array(), error="", log=[]) {
this.resp = resp;
this.data = data;
this.error = error;
this.log = log;
}
}


class cfg {
constructor() {
this.ZLPAwareHost = 1;
this.SkipStorageInit = 0;
this.SkipWrite = 0;
this.MaxPayloadSizeToTargetInBytes = 1048576;
this.MaxPayloadSizeFromTargetInBytes = 4096;
this.MaxXMLSizeInBytes = 4096;
this.bit64 = true;
this.SECTOR_SIZE_IN_BYTES = 4096;
this.MemoryName = "UFS";
this.maxlun = 6;
}
}

export class Firehose {
constructor(cdc) {
this.cdc = cdc;
this.xml = new xmlParser();
this.cfg = new cfg();
this.luns = [];
}

getStatus(resp) {
if (resp.hasOwnProperty("value")) {
let value = resp["value"];
return (value === "ACK" || value === "true");
}
return true;
}

async xmlSend(data, wait=true) {
let dataToSend = new TextEncoder().encode(data).slice(0, this.cfg.MaxXMLSizeInBytes);
await this.cdc?.write(dataToSend, null, wait);

let rData = new Uint8Array();
let counter = 0;
let timeout = 3;
while (!(containsBytes("<response value", rData))) {
let tmp = await this.cdc?.read();
if (compareStringToBytes("", tmp)) {
counter += 1;
await sleep(50);
if (counter > timeout) {
break;
}
}
rData = concatUint8Array([rData, tmp]);
}

const resp = this.xml.getReponse(rData);
const status = this.getStatus(resp);
if (resp.hasOwnProperty("rawmode")) {
if (resp["rawmode"] == "false") {
let log = this.xml.getLog(rData);
return new response(status, rData, "", log)
}
} else {
if (status) {
if (containsBytes("log value=", rData)) {
let log = this.xml.getLog(rData);
return new response(status, rData, "", log);
}
return new response(status, rData);
}
}
return new response(true, rData);
}

getLuns() {
return Array.from({length: this.cfg.maxlun}, (x, i) => i)
}

async configure() {
const connectCmd = `<?xml version=\"1.0\" encoding=\"UTF-8\" ?><data>` +
`<configure MemoryName=\"${this.cfg.MemoryName}\" ` +
`Verbose=\"0\" ` +
`AlwaysValidate=\"0\" ` +
`MaxDigestTableSizeInBytes=\"2048\" ` +
`MaxPayloadSizeToTargetInBytes=\"${this.cfg.MaxPayloadSizeToTargetInBytes}\" ` +
`ZLPAwareHost=\"${this.cfg.ZLPAwareHost}\" ` +
`SkipStorageInit=\"${this.cfg.SkipStorageInit}\" ` +
`SkipWrite=\"${this.cfg.SkipWrite}\"/>` +
`</data>`

await this.xmlSend(connectCmd, false);
this.luns = this.getLuns();
return true;
}

async cmdReadBuffer(physicalPartitionNumber, startSector, numPartitionSectors) {
const data = `<?xml version=\"1.0\" ?><data><read SECTOR_SIZE_IN_BYTES=\"${this.cfg.SECTOR_SIZE_IN_BYTES}\"` +
` num_partition_sectors=\"${numPartitionSectors}\"` +
` physical_partition_number=\"${physicalPartitionNumber}\"` +
` start_sector=\"${startSector}\"/>\n</data>`

let rsp = await this.xmlSend(data);
let resData = new Uint8Array();
if (!rsp.resp) {
return rsp;
} else {
let bytesToRead = this.cfg.SECTOR_SIZE_IN_BYTES * numPartitionSectors;
while (bytesToRead > 0) {
let tmp = await this.cdc.read(Math.min(this.cdc.maxSize, bytesToRead));
const size = tmp.length;
bytesToRead -= size;
resData = concatUint8Array([resData, tmp]);
}

const wd = await this.waitForData();
const info = this.xml.getLog(wd);
rsp = this.xml.getReponse(wd);
if (rsp.hasOwnProperty("value")) {
if (rsp["value"] !== "ACK") {
return new response(false, resData, info);
} else if (rsp.hasOwnProperty("rawmode")) {
if (rsp["rawmode"] === "false") {
return new response(true, resData);
}
}
} else {
console.error("Failed read buffer");
return new response(false, resData, rsp[2]);
}
}
let resp = rsp["value"] === "ACK";
return response(resp, resData, rsp[2]);
}

async waitForData() {
let tmp = new Uint8Array();
let timeout = 0;

while (!containsBytes("response value", tmp)) {
let res = await this.cdc.read();
if (compareStringToBytes("", res)) {
timeout += 1;
if (timeout === 4) {
break;
}
await sleep(20);
}
tmp = concatUint8Array([tmp, res]);
}
return tmp;
}

async cmdProgram(physicalPartitionNumber, startSector, blob, onProgress=()=>{}) {
let total = blob.size;
let sparseformat = false;

let sparseHeader = await Sparse.parseFileHeader(blob.slice(0, Sparse.FILE_HEADER_SIZE));
if (sparseHeader !== null) {
sparseformat = true;
total = await Sparse.getSparseRealSize(blob, sparseHeader);
}

let numPartitionSectors = Math.floor(total / this.cfg.SECTOR_SIZE_IN_BYTES);
if (total % this.cfg.SECTOR_SIZE_IN_BYTES !== 0) {
numPartitionSectors += 1;
}

const data = `<?xml version=\"1.0\" ?><data>\n` +
`<program SECTOR_SIZE_IN_BYTES=\"${this.cfg.SECTOR_SIZE_IN_BYTES}\"` +
` num_partition_sectors=\"${numPartitionSectors}\"` +
` physical_partition_number=\"${physicalPartitionNumber}\"` +
` start_sector=\"${startSector}\" />\n</data>`;
let i = 0;
let bytesWritten = 0;
let rsp = await this.xmlSend(data);

if (rsp.resp) {
for await (let split of Sparse.splitBlob(blob)) {
let offset = 0;
let bytesToWriteSplit = split.size;

while (bytesToWriteSplit > 0) {
const wlen = Math.min(bytesToWriteSplit, this.cfg.MaxPayloadSizeToTargetInBytes);
let wdata = new Uint8Array(await readBlobAsBuffer(split.slice(offset, offset + wlen)));
if (wlen % this.cfg.SECTOR_SIZE_IN_BYTES !== 0) {
let fillLen = (Math.floor(wlen/this.cfg.SECTOR_SIZE_IN_BYTES) * this.cfg.SECTOR_SIZE_IN_BYTES) +
this.cfg.SECTOR_SIZE_IN_BYTES;
const fillArray = new Uint8Array(fillLen-wlen).fill(0x00);
wdata = concatUint8Array([wdata, fillArray]);
}
await this.cdc.write(wdata);
await this.cdc.write(new Uint8Array(0), null, true);
offset += wlen;
bytesWritten += wlen;
bytesToWriteSplit -= wlen;

// Need this for sparse image when the data.length < MaxPayloadSizeToTargetInBytes
// Add ~2.4s to total flash time
if (sparseformat && bytesWritten < total) {
await this.cdc.write(new Uint8Array(0), null, true);
}

if (i % 10 === 0) {
onProgress(bytesWritten/total);
}
i += 1;
}
}

const wd = await this.waitForData();
const response = this.xml.getReponse(wd);
if (response.hasOwnProperty("value")) {
if (response["value"] !== "ACK") {
return false;
}
} else {
return false;
}
}

onProgress(1.0);
return true;
}

async cmdErase(physicalPartitionNumber, startSector, numPartitionSectors) {
const data = `<?xml version=\"1.0\" ?><data>\n` +
`<program SECTOR_SIZE_IN_BYTES=\"${this.cfg.SECTOR_SIZE_IN_BYTES}\"` +
` num_partition_sectors=\"${numPartitionSectors}\"` +
` physical_partition_number=\"${physicalPartitionNumber}\"` +
` start_sector=\"${startSector}\" />\n</data>`;
let pos = 0;
let rsp = await this.xmlSend(data)
let bytesToWrite = this.cfg.SECTOR_SIZE_IN_BYTES * numPartitionSectors;
let empty = new Uint8Array(this.cfg.MaxPayloadSizeToTargetInBytes).fill(0);

if (rsp.resp) {
while (bytesToWrite > 0) {
let wlen = Math.min(bytesToWrite, this.cfg.MaxPayloadSizeToTargetInBytes);
await this.cdc.write(empty.slice(0, wlen));
bytesToWrite -= wlen;
pos += wlen;
await this.cdc.write(new Uint8Array(0));
}

const res = await this.waitForData();
const response = this.xml.getReponse(res);
if (response.hasOwnProperty("value")) {
if (response["value"] !== "ACK") {
throw "Failed to erase: NAK";
}
} else {
throw "Failed to erase no return value";
}
}
return true;
}

async cmdSetBootLunId(lun) {
const data = `<?xml version=\"1.0\" ?><data>\n<setbootablestoragedrive value=\"${lun}\" /></data>`
const val = await this.xmlSend(data);
if (val.resp) {
console.log(`Successfully set bootID to lun ${lun}`);
return true;
} else {
throw `Firehose - Failed to set boot lun ${lun}`;
}
}

async cmdReset() {
let data = "<?xml version=\"1.0\" ?><data><power value=\"reset\"/></data>";
let val = await this.xmlSend(data);
if (val.resp) {
console.log("Reset succeeded");
return true;
} else {
throw "Firehose - Reset failed";
}
}
}
Loading
Loading