From 30ca57de2cdd1e13e76534824311c8d1a8a77c7a Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 17 Jun 2025 11:45:21 +0200 Subject: [PATCH] stages: Add org.osbuild.write-device stage This stage writes a file to a device using dd. This is a rewrite/backport of one of the stages in osbuild-auto. The osbuild-auto stage is used in automotive-image-builder to write the aboot image to the "boot_a" partition, to allow android boot systems to boot. We will want similar functionallity in bootc-image-builder, so it is important to upstream this. Signed-off-by: Alexander Larsson --- stages/org.osbuild.write-device | 49 +++++++++++++++++++++++ stages/org.osbuild.write-device.meta.json | 39 ++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100755 stages/org.osbuild.write-device create mode 100644 stages/org.osbuild.write-device.meta.json diff --git a/stages/org.osbuild.write-device b/stages/org.osbuild.write-device new file mode 100755 index 00000000..d8016848 --- /dev/null +++ b/stages/org.osbuild.write-device @@ -0,0 +1,49 @@ +#!/usr/bin/python3 +""" +Write to device + +""" + +import fcntl +import os +import struct +import subprocess +import sys + +import osbuild.api +from osbuild.util import parsing + + +def blksize(device_path): + req = 0x80081272 # BLKGETSIZE64, result is bytes as unsigned 64-bit integer (uint64) + buf = b' ' * 8 + fmt = 'L' + + with open(device_path, "rb") as dev: + buf = fcntl.ioctl(dev.fileno(), req, buf) + return struct.unpack(fmt, buf)[0] + + +def main(args, devices, options): + src = parsing.parse_location(options.get("from"), args) + device = devices["device"]["path"] + + src_size = os.path.getsize(src) + print(f"src: '{src}' src_size: {src_size}") + device_size = blksize(device) + print(f"device: '{device}' device_size: {device_size}") + if src_size > device_size: + raise ValueError( + f"File too large ({src_size / (1024 * 1024):.1f} mb) for device ({device_size / (1024 * 1024):.1f} mb)") + + cmd = ["dd", f"if={src}", f"of={device}", "status=progress", "conv=fsync"] + print("Running {cmd}") + subprocess.run(cmd, check=True) + + return 0 + + +if __name__ == '__main__': + _args = osbuild.api.arguments() + r = main(_args, _args["devices"], _args["options"]) + sys.exit(r) diff --git a/stages/org.osbuild.write-device.meta.json b/stages/org.osbuild.write-device.meta.json new file mode 100644 index 00000000..8c51c07e --- /dev/null +++ b/stages/org.osbuild.write-device.meta.json @@ -0,0 +1,39 @@ +{ + "summary": "Write a file to a device", + "description": [ + "This allows writing a file to a raw device. This is useful for example", + "to write bootloader or firmware files to custom partitions." + ], + "schema_2": { + "devices": { + "type": "object", + "additionalProperties": true, + "required": [ + "device" + ], + "properties": { + "device": { + "type": "object", + "additionalProperties": true + } + } + }, + "inputs": { + "type": "object", + "additionalProperties": true + }, + "options": { + "additionalProperties": false, + "required": [ + "from" + ], + "properties": { + "from": { + "type": "string", + "description": "The source", + "pattern": "^input:\\/\\/[^\\/]+\\/" + } + } + } + } +}