mirror of
				https://gitlab.com/qemu-project/ipxe.git
				synced 2025-11-03 07:59:06 +08:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			loongarch6
			...
			efivlan
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a2fff570be | |||
| 0bde40d4ba | 
@ -19,9 +19,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
			
		||||
#include <ipxe/efi/Protocol/PxeBaseCode.h>
 | 
			
		||||
#include <ipxe/efi/Protocol/SimpleNetwork.h>
 | 
			
		||||
#include <ipxe/efi/Protocol/UsbIo.h>
 | 
			
		||||
#include <ipxe/efi/Protocol/VlanConfig.h>
 | 
			
		||||
 | 
			
		||||
extern void efi_nullify_snp ( EFI_SIMPLE_NETWORK_PROTOCOL *snp );
 | 
			
		||||
extern void efi_nullify_nii ( EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii );
 | 
			
		||||
extern void efi_nullify_vlan ( EFI_VLAN_CONFIG_PROTOCOL *vcfg );
 | 
			
		||||
extern void efi_nullify_name2 ( EFI_COMPONENT_NAME2_PROTOCOL *name2 );
 | 
			
		||||
extern void efi_nullify_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file );
 | 
			
		||||
extern void efi_nullify_hii ( EFI_HII_CONFIG_ACCESS_PROTOCOL *hii );
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 | 
			
		||||
#include <ipxe/efi/Protocol/HiiConfigAccess.h>
 | 
			
		||||
#include <ipxe/efi/Protocol/HiiDatabase.h>
 | 
			
		||||
#include <ipxe/efi/Protocol/LoadFile.h>
 | 
			
		||||
#include <ipxe/efi/Protocol/VlanConfig.h>
 | 
			
		||||
 | 
			
		||||
/** SNP transmit completion ring size */
 | 
			
		||||
#define EFI_SNP_NUM_TX 32
 | 
			
		||||
@ -51,6 +52,8 @@ struct efi_snp_device {
 | 
			
		||||
	struct list_head rx;
 | 
			
		||||
	/** The network interface identifier */
 | 
			
		||||
	EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
 | 
			
		||||
	/** VLAN configuration protocol */
 | 
			
		||||
	EFI_VLAN_CONFIG_PROTOCOL vcfg;
 | 
			
		||||
	/** Component name protocol */
 | 
			
		||||
	EFI_COMPONENT_NAME2_PROTOCOL name2;
 | 
			
		||||
	/** Load file protocol handle */
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,21 @@ struct vlan_header {
 | 
			
		||||
 */
 | 
			
		||||
#define VLAN_PRIORITY_IS_VALID( priority ) ( (priority) <= 7 )
 | 
			
		||||
 | 
			
		||||
extern unsigned int vlan_tag ( struct net_device *netdev );
 | 
			
		||||
extern unsigned int vlan_tci ( struct net_device *netdev );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the VLAN tag
 | 
			
		||||
 *
 | 
			
		||||
 * @v netdev		Network device
 | 
			
		||||
 * @ret tag		VLAN tag, or 0 if device is not a VLAN device
 | 
			
		||||
 */
 | 
			
		||||
static inline __attribute__ (( always_inline )) unsigned int
 | 
			
		||||
vlan_tag ( struct net_device *netdev ) {
 | 
			
		||||
	return VLAN_TAG ( vlan_tci ( netdev ) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern struct net_device * vlan_find ( struct net_device *trunk,
 | 
			
		||||
				       unsigned int tag );
 | 
			
		||||
extern int vlan_can_be_trunk ( struct net_device *trunk );
 | 
			
		||||
extern int vlan_create ( struct net_device *trunk, unsigned int tag,
 | 
			
		||||
			 unsigned int priority );
 | 
			
		||||
 | 
			
		||||
@ -193,6 +193,48 @@ void efi_nullify_nii ( EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii ) {
 | 
			
		||||
	nii->Id = ( ( intptr_t ) &efi_null_undi );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 * VLAN configuration protocol
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static EFI_STATUS EFIAPI
 | 
			
		||||
efi_null_vlan_set ( EFI_VLAN_CONFIG_PROTOCOL *vcfg __unused,
 | 
			
		||||
		    UINT16 tag __unused, UINT8 priority __unused ) {
 | 
			
		||||
	return EFI_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static EFI_STATUS EFIAPI
 | 
			
		||||
efi_null_vlan_find ( EFI_VLAN_CONFIG_PROTOCOL *vcfg __unused,
 | 
			
		||||
		     UINT16 *filter __unused, UINT16 *count __unused,
 | 
			
		||||
		     EFI_VLAN_FIND_DATA **entries __unused ) {
 | 
			
		||||
	return EFI_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static EFI_STATUS EFIAPI
 | 
			
		||||
efi_null_vlan_remove ( EFI_VLAN_CONFIG_PROTOCOL *vcfg __unused,
 | 
			
		||||
		       UINT16 tag __unused ) {
 | 
			
		||||
	return EFI_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static EFI_VLAN_CONFIG_PROTOCOL efi_null_vlan = {
 | 
			
		||||
	.Set		= efi_null_vlan_set,
 | 
			
		||||
	.Find		= efi_null_vlan_find,
 | 
			
		||||
	.Remove		= efi_null_vlan_remove,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Nullify VLAN configuration interface
 | 
			
		||||
 *
 | 
			
		||||
 * @v vcfg		VLAN configuration protocol
 | 
			
		||||
 */
 | 
			
		||||
void efi_nullify_vlan ( EFI_VLAN_CONFIG_PROTOCOL *vcfg ) {
 | 
			
		||||
 | 
			
		||||
	memcpy ( vcfg, &efi_null_vlan, sizeof ( *vcfg ) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 * Component name protocol
 | 
			
		||||
 | 
			
		||||
@ -1488,6 +1488,135 @@ static EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL efi_snp_device_nii = {
 | 
			
		||||
	.Ipv6Supported	= TRUE, /* This is a raw packet interface, FFS! */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 * VLAN configuration protocol
 | 
			
		||||
 *
 | 
			
		||||
 ******************************************************************************
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create or modify VLAN device
 | 
			
		||||
 *
 | 
			
		||||
 * @v vcfg		VLAN configuration protocol
 | 
			
		||||
 * @v tag		VLAN tag
 | 
			
		||||
 * @v priority		Default VLAN priority
 | 
			
		||||
 * @ret efirc		EFI status code
 | 
			
		||||
 */
 | 
			
		||||
static EFI_STATUS EFIAPI efi_vlan_set ( EFI_VLAN_CONFIG_PROTOCOL *vcfg,
 | 
			
		||||
					UINT16 tag, UINT8 priority ) {
 | 
			
		||||
	struct efi_snp_device *snpdev =
 | 
			
		||||
		container_of ( vcfg, struct efi_snp_device, vcfg );
 | 
			
		||||
	struct net_device *trunk = snpdev->netdev;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	/* Create or modify VLAN device */
 | 
			
		||||
	if ( ( rc = vlan_create ( trunk, tag, priority ) ) != 0 ) {
 | 
			
		||||
		DBGC ( snpdev, "SNPDEV %p could not create VLAN tag %d: %s\n",
 | 
			
		||||
		       snpdev, tag, strerror ( rc ) );
 | 
			
		||||
		return EFIRC ( rc );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DBGC ( snpdev, "SNPDEV %p created VLAN tag %d priority %d\n",
 | 
			
		||||
	       snpdev, tag, priority );
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Find VLAN device(s)
 | 
			
		||||
 *
 | 
			
		||||
 * @v vcfg		VLAN configuration protocol
 | 
			
		||||
 * @v filter		VLAN tag, or NULL to find all VLANs
 | 
			
		||||
 * @v count		Number of VLANs
 | 
			
		||||
 * @v entries		List of VLANs
 | 
			
		||||
 * @ret efirc		EFI status code
 | 
			
		||||
 */
 | 
			
		||||
static EFI_STATUS EFIAPI efi_vlan_find ( EFI_VLAN_CONFIG_PROTOCOL *vcfg,
 | 
			
		||||
					 UINT16 *filter, UINT16 *count,
 | 
			
		||||
					 EFI_VLAN_FIND_DATA **entries ) {
 | 
			
		||||
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
			
		||||
	struct efi_snp_device *snpdev =
 | 
			
		||||
		container_of ( vcfg, struct efi_snp_device, vcfg );
 | 
			
		||||
	struct net_device *trunk = snpdev->netdev;
 | 
			
		||||
	struct net_device *vlan;
 | 
			
		||||
	EFI_VLAN_FIND_DATA *entry;
 | 
			
		||||
	VOID *buffer;
 | 
			
		||||
	unsigned int tag;
 | 
			
		||||
	unsigned int tci;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	EFI_STATUS efirc;
 | 
			
		||||
 | 
			
		||||
	/* Count number of matching VLANs */
 | 
			
		||||
	*count = 0;
 | 
			
		||||
	for ( tag = 1 ; VLAN_TAG_IS_VALID ( tag ) ; tag++ ) {
 | 
			
		||||
		if ( filter && ( tag != *filter ) )
 | 
			
		||||
			continue;
 | 
			
		||||
		if ( ! ( vlan = vlan_find ( trunk, tag ) ) )
 | 
			
		||||
			continue;
 | 
			
		||||
		(*count)++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Allocate buffer to hold results */
 | 
			
		||||
	len = ( (*count) * sizeof ( *entry ) );
 | 
			
		||||
	if ( ( efirc = bs->AllocatePool ( EfiBootServicesData, len,
 | 
			
		||||
					  &buffer ) ) != 0 )
 | 
			
		||||
		return efirc;
 | 
			
		||||
 | 
			
		||||
	/* Fill in buffer */
 | 
			
		||||
	*entries = buffer;
 | 
			
		||||
	entry = *entries;
 | 
			
		||||
	for ( tag = 1 ; VLAN_TAG_IS_VALID ( tag ) ; tag++ ) {
 | 
			
		||||
		if ( filter && ( tag != *filter ) )
 | 
			
		||||
			continue;
 | 
			
		||||
		if ( ! ( vlan = vlan_find ( trunk, tag ) ) )
 | 
			
		||||
			continue;
 | 
			
		||||
		tci = vlan_tci ( vlan );
 | 
			
		||||
		entry->VlanId = VLAN_TAG ( tci );
 | 
			
		||||
		entry->Priority = VLAN_PRIORITY ( tci );
 | 
			
		||||
		assert ( entry->VlanId == tag );
 | 
			
		||||
		entry++;
 | 
			
		||||
	}
 | 
			
		||||
	assert ( entry == &(*entries)[*count] );
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove VLAN device
 | 
			
		||||
 *
 | 
			
		||||
 * @v vcfg		VLAN configuration protocol
 | 
			
		||||
 * @v tag		VLAN tag
 | 
			
		||||
 * @ret efirc		EFI status code
 | 
			
		||||
 */
 | 
			
		||||
static EFI_STATUS EFIAPI efi_vlan_remove ( EFI_VLAN_CONFIG_PROTOCOL *vcfg,
 | 
			
		||||
					   UINT16 tag ) {
 | 
			
		||||
	struct efi_snp_device *snpdev =
 | 
			
		||||
		container_of ( vcfg, struct efi_snp_device, vcfg );
 | 
			
		||||
	struct net_device *trunk = snpdev->netdev;
 | 
			
		||||
	struct net_device *vlan;
 | 
			
		||||
 | 
			
		||||
	/* Identify VLAN device */
 | 
			
		||||
	vlan = vlan_find ( trunk, tag );
 | 
			
		||||
	if ( ! vlan ) {
 | 
			
		||||
		DBGC ( snpdev, "SNPDEV %p could not find VLAN tag %d\n",
 | 
			
		||||
		       snpdev, tag );
 | 
			
		||||
		return EFI_NOT_FOUND;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Remove VLAN device */
 | 
			
		||||
	vlan_destroy ( vlan );
 | 
			
		||||
 | 
			
		||||
	DBGC ( snpdev, "SNPDEV %p removed VLAN tag %d\n", snpdev, tag );
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** VLAN configuration protocol */
 | 
			
		||||
static EFI_VLAN_CONFIG_PROTOCOL efi_vlan = {
 | 
			
		||||
	.Set		= efi_vlan_set,
 | 
			
		||||
	.Find		= efi_vlan_find,
 | 
			
		||||
	.Remove		= efi_vlan_remove,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 * Component name protocol
 | 
			
		||||
@ -1687,6 +1816,9 @@ static int efi_snp_probe ( struct net_device *netdev ) {
 | 
			
		||||
	efi_snp_undi.Fudge -= efi_undi_checksum ( &efi_snp_undi,
 | 
			
		||||
						  sizeof ( efi_snp_undi ) );
 | 
			
		||||
 | 
			
		||||
	/* Populate the VLAN configuration protocol */
 | 
			
		||||
	memcpy ( &snpdev->vcfg, &efi_vlan, sizeof ( snpdev->vcfg ) );
 | 
			
		||||
 | 
			
		||||
	/* Populate the component name structure */
 | 
			
		||||
	efi_snprintf ( snpdev->driver_name,
 | 
			
		||||
		       ( sizeof ( snpdev->driver_name ) /
 | 
			
		||||
@ -1725,6 +1857,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
 | 
			
		||||
			&efi_device_path_protocol_guid, snpdev->path,
 | 
			
		||||
			&efi_nii_protocol_guid, &snpdev->nii,
 | 
			
		||||
			&efi_nii31_protocol_guid, &snpdev->nii,
 | 
			
		||||
			&efi_vlan_config_protocol_guid, &snpdev->vcfg,
 | 
			
		||||
			&efi_component_name2_protocol_guid, &snpdev->name2,
 | 
			
		||||
			&efi_load_file_protocol_guid, &snpdev->load_file,
 | 
			
		||||
			NULL ) ) != 0 ) {
 | 
			
		||||
@ -1811,6 +1944,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
 | 
			
		||||
			&efi_device_path_protocol_guid, snpdev->path,
 | 
			
		||||
			&efi_nii_protocol_guid, &snpdev->nii,
 | 
			
		||||
			&efi_nii31_protocol_guid, &snpdev->nii,
 | 
			
		||||
			&efi_vlan_config_protocol_guid, &snpdev->vcfg,
 | 
			
		||||
			&efi_component_name2_protocol_guid, &snpdev->name2,
 | 
			
		||||
			&efi_load_file_protocol_guid, &snpdev->load_file,
 | 
			
		||||
			NULL ) ) != 0 ) {
 | 
			
		||||
@ -1820,6 +1954,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
 | 
			
		||||
	}
 | 
			
		||||
	efi_nullify_snp ( &snpdev->snp );
 | 
			
		||||
	efi_nullify_nii ( &snpdev->nii );
 | 
			
		||||
	efi_nullify_vlan ( &snpdev->vcfg );
 | 
			
		||||
	efi_nullify_name2 ( &snpdev->name2 );
 | 
			
		||||
	efi_nullify_load_file ( &snpdev->load_file );
 | 
			
		||||
 err_install_protocol_interface:
 | 
			
		||||
 | 
			
		||||
@ -1171,12 +1171,12 @@ static void net_step ( struct process *process __unused ) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the VLAN tag (when VLAN support is not present)
 | 
			
		||||
 * Get the VLAN tag control information (when VLAN support is not present)
 | 
			
		||||
 *
 | 
			
		||||
 * @v netdev		Network device
 | 
			
		||||
 * @ret tag		0, indicating that device is not a VLAN device
 | 
			
		||||
 */
 | 
			
		||||
__weak unsigned int vlan_tag ( struct net_device *netdev __unused ) {
 | 
			
		||||
__weak unsigned int vlan_tci ( struct net_device *netdev __unused ) {
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -199,8 +199,7 @@ static void vlan_sync ( struct net_device *netdev ) {
 | 
			
		||||
 * @v tag		VLAN tag
 | 
			
		||||
 * @ret netdev		VLAN device, if any
 | 
			
		||||
 */
 | 
			
		||||
static struct net_device * vlan_find ( struct net_device *trunk,
 | 
			
		||||
				       unsigned int tag ) {
 | 
			
		||||
struct net_device * vlan_find ( struct net_device *trunk, unsigned int tag ) {
 | 
			
		||||
	struct net_device *netdev;
 | 
			
		||||
	struct vlan_device *vlan;
 | 
			
		||||
 | 
			
		||||
@ -288,17 +287,17 @@ struct net_protocol vlan_protocol __net_protocol = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the VLAN tag
 | 
			
		||||
 * Get the VLAN tag control information
 | 
			
		||||
 *
 | 
			
		||||
 * @v netdev		Network device
 | 
			
		||||
 * @ret tag		VLAN tag, or 0 if device is not a VLAN device
 | 
			
		||||
 * @ret tci		VLAN tag control information, or 0 if not a VLAN device
 | 
			
		||||
 */
 | 
			
		||||
unsigned int vlan_tag ( struct net_device *netdev ) {
 | 
			
		||||
unsigned int vlan_tci ( struct net_device *netdev ) {
 | 
			
		||||
	struct vlan_device *vlan;
 | 
			
		||||
 | 
			
		||||
	if ( netdev->op == &vlan_operations ) {
 | 
			
		||||
		vlan = netdev->priv;
 | 
			
		||||
		return vlan->tag;
 | 
			
		||||
		return ( VLAN_TCI ( vlan->tag, vlan->priority ) );
 | 
			
		||||
	} else {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user