mirror of https://github.com/ipxe/ipxe.git
				
				
				
			[bofm] Add offline BOFM test facility
Testing BOFM involves gaining access to an IBM blade chassis, which is often not practical. Provide a facility for testing BOFM functionality outside of a real IBM blade context. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/1/head
							parent
							
								
									5597d52c21
								
							
						
					
					
						commit
						bdd00e872a
					
				| 
						 | 
				
			
			@ -337,5 +337,6 @@ extern int bofm_register ( struct bofm_device *bofm );
 | 
			
		|||
extern void bofm_unregister ( struct bofm_device *bofm );
 | 
			
		||||
extern int bofm_find_driver ( struct pci_device *pci );
 | 
			
		||||
extern int bofm ( userptr_t bofmtab, struct pci_device *pci );
 | 
			
		||||
extern void bofm_test ( struct pci_device *pci );
 | 
			
		||||
 | 
			
		||||
#endif /* _IPXE_BOFM_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,169 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (C) 2011 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
FILE_LICENCE ( GPL2_OR_LATER );
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ipxe/uaccess.h>
 | 
			
		||||
#include <ipxe/init.h>
 | 
			
		||||
#include <ipxe/pci.h>
 | 
			
		||||
#include <ipxe/ethernet.h>
 | 
			
		||||
#include <ipxe/bofm.h>
 | 
			
		||||
 | 
			
		||||
/** @file
 | 
			
		||||
 *
 | 
			
		||||
 * IBM BladeCenter Open Fabric Manager (BOFM) tests
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** Harvest test table */
 | 
			
		||||
static struct {
 | 
			
		||||
	struct bofm_global_header header;
 | 
			
		||||
	struct bofm_section_header en_header;
 | 
			
		||||
	struct bofm_en en;
 | 
			
		||||
	struct bofm_section_header done;
 | 
			
		||||
} __attribute__ (( packed )) bofmtab_harvest = {
 | 
			
		||||
	.header = {
 | 
			
		||||
		.magic = BOFM_IOAA_MAGIC,
 | 
			
		||||
		.action = BOFM_ACTION_HVST,
 | 
			
		||||
		.version = 0x01,
 | 
			
		||||
		.level = 0x01,
 | 
			
		||||
		.length = sizeof ( bofmtab_harvest ),
 | 
			
		||||
		.profile = "Harvest test profile",
 | 
			
		||||
	},
 | 
			
		||||
	.en_header = {
 | 
			
		||||
		.magic = BOFM_EN_MAGIC,
 | 
			
		||||
		.length = sizeof ( bofmtab_harvest.en ),
 | 
			
		||||
	},
 | 
			
		||||
	.en = {
 | 
			
		||||
		.options = ( BOFM_EN_MAP_PFA | BOFM_EN_USAGE_HARVEST |
 | 
			
		||||
			     BOFM_EN_RQ_HVST_ACTIVE ),
 | 
			
		||||
		.mport = 1,
 | 
			
		||||
	},
 | 
			
		||||
	.done = {
 | 
			
		||||
		.magic = BOFM_DONE_MAGIC,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Update test table */
 | 
			
		||||
static struct {
 | 
			
		||||
	struct bofm_global_header header;
 | 
			
		||||
	struct bofm_section_header en_header;
 | 
			
		||||
	struct bofm_en en;
 | 
			
		||||
	struct bofm_section_header done;
 | 
			
		||||
} __attribute__ (( packed )) bofmtab_update = {
 | 
			
		||||
	.header = {
 | 
			
		||||
		.magic = BOFM_IOAA_MAGIC,
 | 
			
		||||
		.action = BOFM_ACTION_UPDT,
 | 
			
		||||
		.version = 0x01,
 | 
			
		||||
		.level = 0x01,
 | 
			
		||||
		.length = sizeof ( bofmtab_update ),
 | 
			
		||||
		.profile = "Update test profile",
 | 
			
		||||
	},
 | 
			
		||||
	.en_header = {
 | 
			
		||||
		.magic = BOFM_EN_MAGIC,
 | 
			
		||||
		.length = sizeof ( bofmtab_update.en ),
 | 
			
		||||
	},
 | 
			
		||||
	.en = {
 | 
			
		||||
		.options = ( BOFM_EN_MAP_PFA | BOFM_EN_EN_A |
 | 
			
		||||
			     BOFM_EN_USAGE_ENTRY ),
 | 
			
		||||
		.mport = 1,
 | 
			
		||||
		.mac_a = { 0x02, 0x00, 0x69, 0x50, 0x58, 0x45 },
 | 
			
		||||
	},
 | 
			
		||||
	.done = {
 | 
			
		||||
		.magic = BOFM_DONE_MAGIC,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Perform BOFM test
 | 
			
		||||
 *
 | 
			
		||||
 * @v pci		PCI device
 | 
			
		||||
 */
 | 
			
		||||
void bofm_test ( struct pci_device *pci ) {
 | 
			
		||||
	int bofmrc;
 | 
			
		||||
 | 
			
		||||
	printf ( "BOFMTEST using " PCI_FMT "\n", PCI_ARGS ( pci ) );
 | 
			
		||||
 | 
			
		||||
	/* Perform harvest test */
 | 
			
		||||
	printf ( "BOFMTEST performing harvest\n" );
 | 
			
		||||
	bofmtab_harvest.en.busdevfn = pci->busdevfn;
 | 
			
		||||
	DBG_HDA ( 0, &bofmtab_harvest, sizeof ( bofmtab_harvest ) );
 | 
			
		||||
	bofmrc = bofm ( virt_to_user ( &bofmtab_harvest ), pci );
 | 
			
		||||
	printf ( "BOFMTEST harvest result %08x\n", bofmrc );
 | 
			
		||||
	if ( bofmtab_harvest.en.options & BOFM_EN_HVST ) {
 | 
			
		||||
		printf ( "BOFMTEST harvested MAC address %s\n",
 | 
			
		||||
			 eth_ntoa ( &bofmtab_harvest.en.mac_a ) );
 | 
			
		||||
	} else {
 | 
			
		||||
		printf ( "BOFMTEST failed to harvest a MAC address\n" );
 | 
			
		||||
	}
 | 
			
		||||
	DBG_HDA ( 0, &bofmtab_harvest, sizeof ( bofmtab_harvest ) );
 | 
			
		||||
 | 
			
		||||
	/* Perform update test */
 | 
			
		||||
	printf ( "BOFMTEST performing update\n" );
 | 
			
		||||
	bofmtab_update.en.busdevfn = pci->busdevfn;
 | 
			
		||||
	DBG_HDA ( 0, &bofmtab_update, sizeof ( bofmtab_update ) );
 | 
			
		||||
	bofmrc = bofm ( virt_to_user ( &bofmtab_update ), pci );
 | 
			
		||||
	printf ( "BOFMTEST update result %08x\n", bofmrc );
 | 
			
		||||
	if ( bofmtab_update.en.options & BOFM_EN_CSM_SUCCESS ) {
 | 
			
		||||
		printf ( "BOFMTEST updated MAC address to %s\n",
 | 
			
		||||
			 eth_ntoa ( &bofmtab_update.en.mac_a ) );
 | 
			
		||||
	} else {
 | 
			
		||||
		printf ( "BOFMTEST failed to update MAC address\n" );
 | 
			
		||||
	}
 | 
			
		||||
	DBG_HDA ( 0, &bofmtab_update, sizeof ( bofmtab_update ) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Perform BOFM test at initialisation time
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
static void bofm_test_init ( void ) {
 | 
			
		||||
	struct pci_device pci;
 | 
			
		||||
	int busdevfn = -1;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	/* Uncomment the following line and specify the correct PCI
 | 
			
		||||
	 * bus:dev.fn address in order to perform a BOFM test at
 | 
			
		||||
	 * initialisation time.
 | 
			
		||||
	 */
 | 
			
		||||
	// busdevfn = PCI_BUSDEVFN ( <bus>, <dev>, <fn> );
 | 
			
		||||
 | 
			
		||||
	/* Skip test if no PCI bus:dev.fn is defined */
 | 
			
		||||
	if ( busdevfn < 0 )
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Initialise PCI device */
 | 
			
		||||
	memset ( &pci, 0, sizeof ( pci ) );
 | 
			
		||||
	pci_init ( &pci, busdevfn );
 | 
			
		||||
	if ( ( rc = pci_read_config ( &pci ) ) != 0 ) {
 | 
			
		||||
		printf ( "BOFMTEST could not create " PCI_FMT " device: %s\n",
 | 
			
		||||
			 PCI_ARGS ( &pci ), strerror ( rc ) );
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Perform test */
 | 
			
		||||
	bofm_test ( &pci );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** BOFM test initialisation function */
 | 
			
		||||
struct init_fn bofm_test_init_fn __init_fn ( INIT_NORMAL ) = {
 | 
			
		||||
	.initialise = bofm_test_init,
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in New Issue