yunsi-toolbox-vue/lib/partition-table/serializer.ts

57 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { writeU16, writeU32, writeNullTermString } from '../shared/binary-writer';
import type { PartitionTable } from './types';
import { ENTRY_SIZE, ENTRY_MAGIC, MD5_MAGIC, NAME_FIELD_SIZE, TABLE_MAX_SIZE } from './constants';
import { md5 } from './md5';
const U32_MAX = 0xFFFF_FFFF;
function assertU8(val: number, field: string): void {
if (!Number.isInteger(val) || val < 0 || val > 0xFF)
throw new Error(`"${field}" 不是有效的字节值 (0255): ${val}`);
}
function assertU32(val: number, field: string): void {
if (!Number.isInteger(val) || val < 0 || val > U32_MAX)
throw new Error(`"${field}" 不是有效的 32 位无符号整数 (00xFFFFFFFF): ${val}`);
}
/**
* Serialize a PartitionTable to ESP32 binary format.
* Returns a Uint8Array of TABLE_MAX_SIZE filled with 0xFF for empty space.
*/
export function serializeBinary(table: PartitionTable): Uint8Array {
const buf = new Uint8Array(TABLE_MAX_SIZE);
buf.fill(0xFF);
let offset = 0;
for (const entry of table.entries) {
if (offset + ENTRY_SIZE > TABLE_MAX_SIZE - ENTRY_SIZE) {
throw new Error(`分区表条目过多,超过最大容量 (最多 ${Math.floor((TABLE_MAX_SIZE - ENTRY_SIZE) / ENTRY_SIZE)} 条)`);
}
assertU8(entry.type, '类型');
assertU8(entry.subtype, '子类型');
assertU32(entry.offset, '偏移量');
assertU32(entry.size, '大小');
assertU32(entry.flags, '标志');
writeU16(buf, offset, ENTRY_MAGIC);
buf[offset + 2] = entry.type;
buf[offset + 3] = entry.subtype;
writeU32(buf, offset + 4, entry.offset);
writeU32(buf, offset + 8, entry.size);
writeNullTermString(buf, offset + 12, entry.name, NAME_FIELD_SIZE);
writeU32(buf, offset + 28, entry.flags);
offset += ENTRY_SIZE;
}
// Write MD5 checksum entry
// [0..1] = MD5_MAGIC, [2..15] = 0xFF padding, [16..31] = MD5 hash
writeU16(buf, offset, MD5_MAGIC);
// [2..15] already 0xFF from fill
const hash = md5(buf.subarray(0, offset));
buf.set(hash, offset + 16);
return buf;
}