]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[blob] Add an abstraction of an openable data blob
authorMichael Brown <mcb30@ipxe.org>
Wed, 15 Jul 2026 22:28:38 +0000 (23:28 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 15 Jul 2026 22:32:13 +0000 (23:32 +0100)
Within the iPXE data transfer interface model, openers are fully
asynchronous and may not deliver any data until after the opener has
returned.

Provide a trivial openable data blob object (as a generalisation of
the "hello world" data transfer interface example code) that will
simply deliver a single fixed blob of data to its parent interface and
then close itself.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/blob.c [new file with mode: 0644]
src/core/hw.c [deleted file]
src/include/ipxe/blob.h [new file with mode: 0644]
src/include/ipxe/errfile.h

diff --git a/src/core/blob.c b/src/core/blob.c
new file mode 100644 (file)
index 0000000..cc5ea5a
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
+
+#include <string.h>
+#include <errno.h>
+#include <ipxe/malloc.h>
+#include <ipxe/xfer.h>
+#include <ipxe/process.h>
+#include <ipxe/blob.h>
+
+/** @file
+ *
+ * Openable data blobs
+ *
+ * Within the iPXE data transfer interface model, openers are fully
+ * asynchronous and may not deliver any data until after the opener
+ * has returned.  An openable data blob provides a way to open an
+ * interface that will then simply return a single fixed blob of data.
+ */
+
+/** An openable data blob */
+struct blob {
+       /** Reference count */
+       struct refcnt refcnt;
+       /** Data transfer interface */
+       struct interface xfer;
+       /** Download process */
+       struct process process;
+       /** Data */
+       const void *data;
+       /** Length of data */
+       size_t len;
+};
+
+/**
+ * Close data blob
+ *
+ * @v blob             Data blob
+ * @v rc               Reason for close
+ */
+static void blob_close ( struct blob *blob, int rc ) {
+
+       /* Stop process */
+       process_del ( &blob->process );
+
+       /* Shut down interface */
+       intf_shutdown ( &blob->xfer, rc );
+}
+
+/**
+ * Process data blob
+ *
+ * @v blob             Data blob
+ */
+static void blob_step ( struct blob *blob ) {
+       int rc;
+
+       /* Deliver data when window opens */
+       if ( xfer_window ( &blob->xfer ) ) {
+               rc = xfer_deliver_raw ( &blob->xfer, blob->data, blob->len );
+               blob_close ( blob, rc );
+       }
+}
+
+/** Data blob interface operations */
+static struct interface_operation blob_xfer_op[] = {
+       INTF_OP ( xfer_window_changed, struct blob *, blob_step ),
+       INTF_OP ( intf_close, struct blob *, blob_close ),
+};
+
+/** Data blob interface descriptor */
+static struct interface_descriptor blob_xfer_desc =
+       INTF_DESC ( struct blob, xfer, blob_xfer_op );
+
+/** Data blob process descriptor */
+static struct process_descriptor blob_process_desc =
+       PROC_DESC_ONCE ( struct blob, process, blob_step );
+
+/**
+ * Open data blob
+ *
+ * @v xfer             Data transfer interface
+ * @v data             Data
+ * @v len              Length of data
+ * @ret rc             Return status code
+ */
+int blob_open ( struct interface *xfer, const void *data, size_t len ) {
+       struct blob *blob;
+       void *copy;
+
+       /* Allocate and initialise structure */
+       blob = zalloc ( sizeof ( *blob ) + len );
+       if ( ! blob )
+               return -ENOMEM;
+       ref_init ( &blob->refcnt, NULL );
+       intf_init ( &blob->xfer, &blob_xfer_desc, &blob->refcnt );
+       process_init ( &blob->process, &blob_process_desc, &blob->refcnt );
+       copy = ( ( ( void * ) blob ) + sizeof ( *blob ) );
+       blob->data = copy;
+       blob->len = len;
+       memcpy ( copy, data, len );
+
+       /* Attach parent interface, mortalise self, and return */
+       intf_plug_plug ( &blob->xfer, xfer );
+       ref_put ( &blob->refcnt );
+       return 0;
+}
diff --git a/src/core/hw.c b/src/core/hw.c
deleted file mode 100644 (file)
index 91736a6..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ipxe/refcnt.h>
-#include <ipxe/process.h>
-#include <ipxe/xfer.h>
-#include <ipxe/open.h>
-
-/** @file
- *
- * "Hello World" data source
- *
- */
-
-struct hw {
-       struct refcnt refcnt;
-       struct interface xfer;
-       struct process process;
-};
-
-static const char hw_msg[] = "Hello world!\n";
-
-static void hw_finished ( struct hw *hw, int rc ) {
-       intf_shutdown ( &hw->xfer, rc );
-       process_del ( &hw->process );
-}
-
-static void hw_step ( struct hw *hw ) {
-       int rc;
-
-       if ( xfer_window ( &hw->xfer ) ) {
-               rc = xfer_deliver_raw ( &hw->xfer, hw_msg, sizeof ( hw_msg ) );
-               hw_finished ( hw, rc );
-       }
-}
-
-static struct interface_operation hw_xfer_operations[] = {
-       INTF_OP ( xfer_window_changed, struct hw *, hw_step ),
-       INTF_OP ( intf_close, struct hw *, hw_finished ),
-};
-
-static struct interface_descriptor hw_xfer_desc =
-       INTF_DESC ( struct hw, xfer, hw_xfer_operations );
-
-static struct process_descriptor hw_process_desc =
-       PROC_DESC_ONCE ( struct hw, process, hw_step );
-
-static int hw_open ( struct interface *xfer, struct uri *uri __unused ) {
-       struct hw *hw;
-
-       /* Allocate and initialise structure */
-       hw = zalloc ( sizeof ( *hw ) );
-       if ( ! hw )
-               return -ENOMEM;
-       ref_init ( &hw->refcnt, NULL );
-       intf_init ( &hw->xfer, &hw_xfer_desc, &hw->refcnt );
-       process_init ( &hw->process, &hw_process_desc, &hw->refcnt );
-
-       /* Attach parent interface, mortalise self, and return */
-       intf_plug_plug ( &hw->xfer, xfer );
-       ref_put ( &hw->refcnt );
-       return 0;
-}
-
-struct uri_opener hw_uri_opener __uri_opener = {
-       .scheme = "hw",
-       .open = hw_open,
-};
diff --git a/src/include/ipxe/blob.h b/src/include/ipxe/blob.h
new file mode 100644 (file)
index 0000000..20f7277
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _IPXE_BLOB_H
+#define _IPXE_BLOB_H
+
+/** @file
+ *
+ * Openable data blobs
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+FILE_SECBOOT ( PERMITTED );
+
+#include <stdint.h>
+#include <ipxe/interface.h>
+
+extern int blob_open ( struct interface *xfer, const void *data, size_t len );
+
+#endif /* _IPXE_BLOB_H */
index 925530fa7154ada2dd7599c1c6eae9a60d988673..c6ebfd67feee2a57edd3cf4ef2ef0ff8ce3b9fea 100644 (file)
@@ -41,7 +41,7 @@ FILE_SECBOOT ( PERMITTED );
 #define ERRFILE_asprintf              ( ERRFILE_CORE | 0x00000000 )
 #define ERRFILE_downloader            ( ERRFILE_CORE | 0x00010000 )
 #define ERRFILE_exec                  ( ERRFILE_CORE | 0x00020000 )
-#define ERRFILE_hw                    ( ERRFILE_CORE | 0x00030000 )
+#define ERRFILE_blob                  ( ERRFILE_CORE | 0x00030000 )
 #define ERRFILE_iobuf                 ( ERRFILE_CORE | 0x00040000 )
 #define ERRFILE_job                   ( ERRFILE_CORE | 0x00050000 )
 #define ERRFILE_linebuf                       ( ERRFILE_CORE | 0x00060000 )