]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[bofm] Allow BOFM tests to be run without a BOFM-capable device driver
authorMichael Brown <mcb30@ipxe.org>
Tue, 29 Apr 2025 12:39:12 +0000 (13:39 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 29 Apr 2025 12:39:12 +0000 (13:39 +0100)
The BOFM tests are not part of the standard unit test suite, since
they are designed to allow for exercising real BOFM driver code
outside of the context of a real IBM blade server.

Allow for the BOFM tests to be run without a real BOFM driver, by
providing a dummy driver for the specified PCI test device.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/bofm.h
src/tests/bofm_test.c

index bc994ea8b174cf7802801d6da196501206a7dd3f..816effd4dfd28c95cef4ff652caf80ce19a11baf 100644 (file)
@@ -328,6 +328,9 @@ struct bofm_operations {
 #define __bofm_driver
 #endif
 
+/** Declare a BOFM test driver */
+#define __bofm_test_driver __table_entry ( BOFM_DRIVERS, 02 )
+
 /**
  * Initialise BOFM device
  *
index dbef1eb9071313817d32886643123485c0a1c505..6d472bc7eb1ad37115577f3987d9f7eeb1ad75e2 100644 (file)
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
+#include <byteswap.h>
 #include <ipxe/init.h>
 #include <ipxe/pci.h>
 #include <ipxe/ethernet.h>
@@ -135,6 +136,109 @@ void bofm_test ( struct pci_device *pci ) {
        DBG_HDA ( 0, &bofmtab_update, sizeof ( bofmtab_update ) );
 }
 
+/**
+ * Harvest dummy Ethernet MAC
+ *
+ * @v bofm             BOFM device
+ * @v mport            Multi-port index
+ * @v mac              MAC to fill in
+ * @ret rc             Return status code
+ */
+static int bofm_dummy_harvest ( struct bofm_device *bofm, unsigned int mport,
+                               uint8_t *mac ) {
+       struct {
+               uint16_t vendor;
+               uint16_t device;
+               uint16_t mport;
+       } __attribute__ (( packed )) dummy_mac;
+
+       /* Construct dummy MAC address */
+       dummy_mac.vendor = cpu_to_be16 ( bofm->pci->vendor );
+       dummy_mac.device = cpu_to_be16 ( bofm->pci->device );
+       dummy_mac.mport = cpu_to_be16 ( mport );
+       memcpy ( mac, &dummy_mac, sizeof ( dummy_mac ) );
+       printf ( "BOFMTEST mport %d constructed dummy MAC %s\n",
+                mport, eth_ntoa ( mac ) );
+
+       return 0;
+}
+
+/**
+ * Update Ethernet MAC for BOFM
+ *
+ * @v bofm             BOFM device
+ * @v mport            Multi-port index
+ * @v mac              MAC to fill in
+ * @ret rc             Return status code
+ */
+static int bofm_dummy_update ( struct bofm_device *bofm __unused,
+                              unsigned int mport, const uint8_t *mac ) {
+
+       printf ( "BOFMTEST mport %d asked to update MAC to %s\n",
+                mport, eth_ntoa ( mac ) );
+       return 0;
+}
+
+/** Dummy BOFM operations */
+static struct bofm_operations bofm_dummy_operations = {
+       .harvest = bofm_dummy_harvest,
+       .update = bofm_dummy_update,
+};
+
+/** Dummy BOFM device */
+static struct bofm_device bofm_dummy;
+
+/**
+ * Probe dummy BOFM device
+ *
+ * @v pci              PCI device
+ * @v id               PCI ID
+ * @ret rc             Return status code
+ */
+static int bofm_dummy_probe ( struct pci_device *pci ) {
+       int rc;
+
+       /* Ignore probe for any other devices */
+       if ( pci->busdevfn != bofm_dummy.pci->busdevfn )
+               return 0;
+
+       /* Register BOFM device */
+       if ( ( rc = bofm_register ( &bofm_dummy ) ) != 0 )
+               return rc;
+
+       printf ( "BOFMTEST using dummy BOFM driver\n" );
+       return 0;
+}
+
+/**
+ * Remove dummy BOFM device
+ *
+ * @v pci              PCI device
+ */
+static void bofm_dummy_remove ( struct pci_device *pci ) {
+
+       /* Ignore removal for any other devices */
+       if ( pci->busdevfn != bofm_dummy.pci->busdevfn )
+               return;
+
+       /* Unregister BOFM device */
+       bofm_unregister ( &bofm_dummy );
+}
+
+/** Dummy BOFM driver PCI IDs */
+static struct pci_device_id bofm_dummy_ids[1] = {
+       { .name = "dummy" },
+};
+
+/** Dummy BOFM driver */
+struct pci_driver bofm_dummy_driver __bofm_test_driver = {
+       .ids = bofm_dummy_ids,
+       .id_count = ( sizeof ( bofm_dummy_ids ) /
+                     sizeof ( bofm_dummy_ids[0] ) ),
+       .probe = bofm_dummy_probe,
+       .remove = bofm_dummy_remove,
+};
+
 /**
  * Perform BOFM test at initialisation time
  *
@@ -148,7 +252,7 @@ static void bofm_test_init ( void ) {
         * bus:dev.fn address in order to perform a BOFM test at
         * initialisation time.
         */
-       // busdevfn = PCI_BUSDEVFN ( <bus>, <dev>, <fn> );
+       // busdevfn = PCI_BUSDEVFN ( <segment>, <bus>, <dev>, <fn> );
 
        /* Skip test if no PCI bus:dev.fn is defined */
        if ( busdevfn < 0 )
@@ -163,6 +267,11 @@ static void bofm_test_init ( void ) {
                return;
        }
 
+       /* Initialise dummy BOFM device */
+       bofm_init ( &bofm_dummy, &pci, &bofm_dummy_operations );
+       bofm_dummy_ids[0].vendor = pci.vendor;
+       bofm_dummy_ids[0].device = pci.device;
+
        /* Perform test */
        bofm_test ( &pci );
 }