[bofm] Allow BOFM tests to be run without a BOFM-capable device driver

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>
This commit is contained in:
Michael Brown
2025-04-29 13:39:12 +01:00
parent 4e909cc2b0
commit 0800723845
2 changed files with 113 additions and 1 deletions

View 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
*

View 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 );
}