64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
import struct
|
|
|
|
|
|
SECTOR_BYTES = 512
|
|
PARTITION_LBA = 1
|
|
PARTITION_SECTORS = 8192
|
|
RESERVED_SECTORS = 1
|
|
FAT_COUNT = 2
|
|
FAT_SECTORS = 32
|
|
ROOT_ENTRIES = 512
|
|
ROOT_SECTORS = ROOT_ENTRIES * 32 // SECTOR_BYTES
|
|
DATA_RELATIVE_SECTOR = RESERVED_SECTORS + FAT_COUNT * FAT_SECTORS + ROOT_SECTORS
|
|
|
|
|
|
def build_fixture(path: Path, config_file: bytes) -> Path:
|
|
if len(config_file) != 64 * 1024:
|
|
raise ValueError("配置文件必须为 64 KiB")
|
|
image = bytearray((PARTITION_LBA + PARTITION_SECTORS) * SECTOR_BYTES)
|
|
image[510:512] = b"\x55\xaa"
|
|
partition_entry = 446
|
|
image[partition_entry + 4] = 0x06
|
|
struct.pack_into("<II", image, partition_entry + 8, PARTITION_LBA, PARTITION_SECTORS)
|
|
|
|
boot = PARTITION_LBA * SECTOR_BYTES
|
|
image[boot : boot + 3] = b"\xeb\x3c\x90"
|
|
image[boot + 3 : boot + 11] = b"MSDOS5.0"
|
|
struct.pack_into("<H", image, boot + 11, SECTOR_BYTES)
|
|
image[boot + 13] = 1
|
|
struct.pack_into("<H", image, boot + 14, RESERVED_SECTORS)
|
|
image[boot + 16] = FAT_COUNT
|
|
struct.pack_into("<H", image, boot + 17, ROOT_ENTRIES)
|
|
struct.pack_into("<H", image, boot + 19, PARTITION_SECTORS)
|
|
image[boot + 21] = 0xF8
|
|
struct.pack_into("<H", image, boot + 22, FAT_SECTORS)
|
|
image[boot + 510 : boot + 512] = b"\x55\xaa"
|
|
|
|
fat = bytearray(FAT_SECTORS * SECTOR_BYTES)
|
|
struct.pack_into("<HH", fat, 0, 0xFFF8, 0xFFFF)
|
|
clusters = len(config_file) // SECTOR_BYTES
|
|
for index in range(clusters):
|
|
cluster = 2 + index
|
|
struct.pack_into("<H", fat, cluster * 2, 0xFFFF if index == clusters - 1 else cluster + 1)
|
|
first_fat = boot + RESERVED_SECTORS * SECTOR_BYTES
|
|
image[first_fat : first_fat + len(fat)] = fat
|
|
image[first_fat + len(fat) : first_fat + 2 * len(fat)] = fat
|
|
|
|
root = boot + (RESERVED_SECTORS + FAT_COUNT * FAT_SECTORS) * SECTOR_BYTES
|
|
image[root : root + 11] = b"MSCCFG BIN"
|
|
image[root + 11] = 0x20
|
|
struct.pack_into("<H", image, root + 26, 2)
|
|
struct.pack_into("<I", image, root + 28, len(config_file))
|
|
data = boot + DATA_RELATIVE_SECTOR * SECTOR_BYTES
|
|
image[data : data + len(config_file)] = config_file
|
|
path.write_bytes(image)
|
|
return path
|
|
|
|
|
|
def first_fat_offset() -> int:
|
|
return (PARTITION_LBA + RESERVED_SECTORS) * SECTOR_BYTES
|
|
|