@aepyornis/fastboot.ts 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # fastboot.ts
2
2
 
3
+ Android Fastboot implementation for WebUSB
4
+
3
5
  ```sh
4
6
  npm install
5
7
  npm run build
@@ -11,7 +13,7 @@ npm run build
11
13
  src/sparse.ts sparse image utilities Copyright (c) 2021 Danny Lin <danny@kdrag0n.dev>
12
14
 
13
15
  ```js
14
- import { FastbootClient, FashbootFlasher } from "@aepyornis/fastboot.ts"
16
+ import { FastbootClient, FastbootFlasher } from "@aepyornis/fastboot.ts"
15
17
 
16
18
  const client = await FastbootClient.create()
17
19
 
@@ -21,31 +23,12 @@ await client.getVar("product")
21
23
 
22
24
  // flash CalyxOS
23
25
  import OpfsBlobStore from "@aepyornis/opfs_blob_store"
24
- const bs = await OpfsBlobStore.create()
25
- const hash = "a4434edb21e5e12a00ab9949f48f06c48169adcaeb4dce644857e1528b275274"
26
- const url = "https://release.calyxinstitute.org/lynx-factory-25605200.zip"
27
- await bs.fetch(hash, url)
28
- const file = await bs.get(hash)
29
-
30
- const instructions = `
31
- fastboot --set-active=other reboot-bootloader
32
- sleep 5
33
- fastboot flash --slot=other bootloader bootloader-lynx-lynx-15.2-12878710.img
34
- fastboot --set-active=other reboot-bootloader
35
- sleep 5
36
- fastboot flash --slot=other radio radio-lynx-g5300q-241205-250127-B-12973597.img
37
- fastboot --set-active=other reboot-bootloader
38
- sleep 5
39
- fastboot flash --slot=other radio radio-lynx-g5300q-241205-250127-B-12973597.img
40
- fastboot --set-active=other reboot-bootloader
41
- sleep 5
42
- fastboot erase avb_custom_key
43
- fastboot flash avb_custom_key avb_custom_key.img
44
- fastboot --skip-reboot -w update image-lynx-bp1a.250305.019.zip
45
- fastboot reboot-bootloader
46
- `
47
-
26
+ const opfs = await OpfsBlobStore.create()
27
+ const hash = "db9ab330a1b5d5ebf131f378dca8b5f6400337f438a97aef2a09a1ba88f3935c"
28
+ const url = "https://release.calyxinstitute.org/bangkk-factory-25608210.zip"
29
+ await opfs.fetch(hash, url)
30
+ const file = await opfs.get(hash)
48
31
  const client = await FastbootClient.create()
49
- const deviceFlasher = new FastbootFlasher()
50
- await deviceFlasher.run(instructions)
32
+ const deviceFlasher = new FastbootFlasher(client, file)
33
+ await deviceFlasher.runFlashAll()
51
34
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aepyornis/fastboot.ts",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Fastboot using WebUSB",
5
5
  "main": "src/index.ts",
6
6
  "scripts": {
package/src/client.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BlobWriter, Entry } from "@zip.js/zip.js"
2
2
  import { IMAGES } from "./images"
3
3
  import { parseBlobHeader, splitBlob, fromRaw } from "./sparse"
4
- import { FastbootDevice } from "./device"
4
+ import { FastbootDevice, FastbootDeviceError } from "./device"
5
5
 
6
6
  export class FastbootError extends Error {}
7
7
 
@@ -20,16 +20,27 @@ interface Logger {
20
20
  export class FastbootClient {
21
21
  fd: FastbootDevice
22
22
  logger: Logger
23
+ var_cache: Object
23
24
 
24
25
  constructor(usb_device: USBDevice, logger: Logger = window.console) {
25
26
  this.fd = new FastbootDevice(usb_device, logger)
26
27
  this.logger = logger
28
+ this.var_cache = {}
27
29
  }
28
30
 
29
31
  async getVar(variable: string) {
30
32
  return this.fd.getVar(variable)
31
33
  }
32
34
 
35
+ async getVarCache(variable: string) {
36
+ if (this.var_cache[variable]) {
37
+ return this.var_cache[variable]
38
+ } else {
39
+ this.var_cache[variable] = await this.getVar(variable)
40
+ return this.var_cache[variable]
41
+ }
42
+ }
43
+
33
44
  async lock() {
34
45
  await this.flashing("lock")
35
46
  if (await this.unlocked()) {
@@ -139,7 +150,6 @@ export class FastbootClient {
139
150
  ) {
140
151
  return true
141
152
  }
142
-
143
153
  this.logger.log(`ACTION NEEDED: flashing ${command}`)
144
154
  await this.fd.exec(`flashing ${command}`)
145
155
  await this.fd.waitForReconnect()
@@ -273,11 +283,21 @@ export class FastbootClient {
273
283
  }
274
284
 
275
285
  async unlocked() {
276
- return (await this.getVar("unlocked")) === "yes"
286
+ const product = await this.getVarCache("product")
287
+ if (product === "bangkk") {
288
+ return (await this.getVar("securestate")) === "flashing_unlocked"
289
+ } else {
290
+ return (await this.getVar("unlocked")) === "yes"
291
+ }
277
292
  }
278
293
 
279
294
  async locked() {
280
- return (await this.getVar("unlocked")) === "no"
295
+ const product = await this.getVarCache("product")
296
+ if (product === "bangkk") {
297
+ return (await this.getVar("securestate")) === "flashing_locked"
298
+ } else {
299
+ return (await this.getVar("unlocked")) === "no"
300
+ }
281
301
  }
282
302
 
283
303
  async currentSlot() {
@@ -301,6 +321,32 @@ export class FastbootClient {
301
321
  return (await this.getVar("is-userspace")) === "yes"
302
322
  }
303
323
 
324
+ // tested on bangkk only
325
+ async getUnlockData() {
326
+ await client.fd.exec(`oem get_unlock_data`)
327
+
328
+ let data = ""
329
+
330
+ for (let packet of client.fd.session.packets) {
331
+ if (packet.command) {
332
+ continue
333
+ } else if (packet.status === "INFO") {
334
+ let message = packet.message.replace("(bootloader)", "").trim()
335
+ if (message === "Unlock data:") {
336
+ continue
337
+ } else {
338
+ data += message
339
+ }
340
+ } else if (packet.status === "OKAY") {
341
+ break
342
+ } else {
343
+ throw new Error(`packet status == ${packet.status}`)
344
+ }
345
+ }
346
+
347
+ return data
348
+ }
349
+
304
350
  static async create() {
305
351
  return new FastbootClient(await this.requestUsbDevice(), window.console)
306
352
  }
package/src/flasher.ts CHANGED
@@ -101,6 +101,23 @@ export class FastbootFlasher {
101
101
  this.reader = new ZipReader(new BlobReader(blob))
102
102
  }
103
103
 
104
+ // parses and runs flash-all.sh. it ignores all shell commands
105
+ // except fastboot or sleep
106
+ async runFlashAll() {
107
+ const entries: Entry[] = await this.reader.getEntries()
108
+ const flashAllSh = await getEntry(entries, "flash-all.sh").getData(
109
+ new TextWriter(),
110
+ )
111
+
112
+ const instructions = flashAllSh
113
+ .split("\n")
114
+ .map((x) => x.trim())
115
+ .filter((x) => x.slice(0, 9) === "fastboot " || x.slice(0, 5) === "sleep")
116
+ .join("\n")
117
+
118
+ return this.run(instructions)
119
+ }
120
+
104
121
  async run(instructions: text) {
105
122
  const entries: Entry[] = await this.reader.getEntries() // io with factory.zip
106
123
  const commands: Instruction[] = parseInstructions(instructions)