Files
banban/tools/customer_fs/generate_macos.py
T

77 lines
2.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Generate a disk-2.0 LittleFS customer_fs image on macOS."""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
from littlefs import LittleFS, UserContext
IMAGE_SIZE = 589824
BLOCK_SIZE = 4096
BLOCK_COUNT = 144
DISK_VERSION = 0x00020000
def fail(message: str) -> None:
raise SystemExit(f"customer_fs generation failed: {message}")
def collect_source_files(source: Path) -> list[Path]:
if not source.is_dir():
fail(f"source directory does not exist: {source}")
entries = sorted(source.iterdir(), key=lambda path: path.name.encode("utf-8"))
if not entries:
fail(f"source directory is empty: {source}")
invalid = [entry.name for entry in entries if not entry.is_file() or entry.name.startswith(".")]
if invalid:
fail(
"source must contain only visible root-level files; invalid entries: "
+ ", ".join(invalid)
)
return entries
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--source", required=True, type=Path)
parser.add_argument("--output", required=True, type=Path)
args = parser.parse_args()
files = collect_source_files(args.source)
context = UserContext(buffsize=IMAGE_SIZE)
fs = LittleFS(
context=context,
mount=False,
block_size=BLOCK_SIZE,
block_count=BLOCK_COUNT,
read_size=16,
prog_size=16,
cache_size=256,
lookahead_size=32,
block_cycles=500,
disk_version=DISK_VERSION,
)
fs.format()
fs.mount()
try:
for source_file in files:
with source_file.open("rb") as source_handle:
with fs.open("/" + source_file.name, "wb") as image_handle:
while chunk := source_handle.read(64 * 1024):
image_handle.write(chunk)
finally:
fs.unmount()
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_bytes(context.buffer)
print(f"generated {args.output} from {len(files)} files")
return 0
if __name__ == "__main__":
sys.exit(main())