blobs: Add code to extract, mount, and flatten APEX modules
This commit is contained in:
parent
dca5d152d8
commit
de09864601
1 changed files with 91 additions and 0 deletions
91
src/blobs/apex.ts
Normal file
91
src/blobs/apex.ts
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import { promises as fs } from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
import * as unzipit from 'unzipit'
|
||||||
|
|
||||||
|
import { listFilesRecursive, TempState } from '../util/fs'
|
||||||
|
import { run } from '../util/process'
|
||||||
|
import { NodeFileReader } from '../util/zip'
|
||||||
|
import { BlobEntry } from './entry'
|
||||||
|
import { combinedPartPathToEntry } from './file_list'
|
||||||
|
|
||||||
|
export const ANDROID_INFO = 'android-info.txt'
|
||||||
|
|
||||||
|
export type FirmwareImages = Map<string, ArrayBuffer>
|
||||||
|
|
||||||
|
async function listPayload(partition: string, apexName: string, img: ArrayBuffer, tmp: TempState) {
|
||||||
|
// Extract image
|
||||||
|
let imgPath = `${tmp.dir}/apex_payload.img`
|
||||||
|
await fs.writeFile(imgPath, new DataView(img))
|
||||||
|
|
||||||
|
// Mount
|
||||||
|
let mountPoint = `${tmp.dir}/payload`
|
||||||
|
await fs.mkdir(mountPoint)
|
||||||
|
await run(`mount -t ext4 -o ro ${imgPath} ${mountPoint}`)
|
||||||
|
tmp.mounts.push(mountPoint)
|
||||||
|
|
||||||
|
// Extract files, including apex_metadata.pb
|
||||||
|
let entries: Array<BlobEntry> = []
|
||||||
|
for await (let file of listFilesRecursive(mountPoint)) {
|
||||||
|
let partPath = path.relative(mountPoint, file)
|
||||||
|
let entry = combinedPartPathToEntry(partition, `${partition}/apex/${apexName}/${partPath}`)
|
||||||
|
// I don't know of a way to make Soong copy files to a non-standard path ($part/apex/*)
|
||||||
|
entry.disableSoong = true
|
||||||
|
// Copy directly from mounted image
|
||||||
|
entry.diskSrcPath = file
|
||||||
|
|
||||||
|
entries.push(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function flattenApex(partition: string, zipPath: string, tmp: TempState) {
|
||||||
|
let apexName = path.basename(zipPath, '.apex')
|
||||||
|
let entries: Array<BlobEntry> = []
|
||||||
|
let reader = new NodeFileReader(zipPath)
|
||||||
|
|
||||||
|
try {
|
||||||
|
let { entries: zipEntries } = await unzipit.unzip(reader)
|
||||||
|
|
||||||
|
for (let [name, zipEntry] of Object.entries(zipEntries)) {
|
||||||
|
if (name == 'apex_pubkey') {
|
||||||
|
// Extract public key file to tmp
|
||||||
|
let pubkeyPath = `${tmp.dir}/apex_pubkey`
|
||||||
|
await fs.writeFile(pubkeyPath, new DataView(await zipEntry.arrayBuffer()))
|
||||||
|
|
||||||
|
// Add entry
|
||||||
|
let entry = combinedPartPathToEntry(partition, `${partition}/apex/${apexName}/apex_pubkey`)
|
||||||
|
entry.diskSrcPath = pubkeyPath
|
||||||
|
entries.push(entry)
|
||||||
|
} else if (name == 'apex_payload.img') {
|
||||||
|
// Mount and add payload files as entries
|
||||||
|
let img = await zipEntry.arrayBuffer()
|
||||||
|
let payloadEntries = await listPayload(partition, apexName, img, tmp)
|
||||||
|
entries.push(...payloadEntries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries
|
||||||
|
} finally {
|
||||||
|
await reader.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function flattenAllApexs(rawEntries: Array<BlobEntry>, srcDir: string, tmp: TempState) {
|
||||||
|
let entries = new Set(rawEntries)
|
||||||
|
for (let entry of rawEntries) {
|
||||||
|
if (path.extname(entry.path) != '.apex') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten and add new entries
|
||||||
|
let apexPath = `${srcDir}/${entry.srcPath}`
|
||||||
|
let apexEntries = await flattenApex(entry.partition, apexPath, tmp)
|
||||||
|
apexEntries.forEach(e => entries.add(e))
|
||||||
|
|
||||||
|
// Remove the APEX blob entry
|
||||||
|
entries.delete(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(entries)
|
||||||
|
}
|
Loading…
Reference in a new issue