summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-01-15 21:36:08 +0000
committerMichael Brown <mcb30@ipxe.org>2023-01-15 21:36:08 +0000
commit5a2fa6040e17562ce742df09aa20b8774b3879c5 (patch)
tree608b47590365c52ca7e6c767d32d6487689e7312
parentc4c03e5be867a9b7be4dc48fe6576deca1dce8d8 (diff)
downloadqemu-ipxe-5a2fa6040e17562ce742df09aa20b8774b3879c5.tar.gz
[autoboot] Include VLAN tag in filter for identifying autoboot device
When chainloading iPXE from a VLAN device, the MAC address of the loaded image's device handle will match the MAC address of the trunk device created by iPXE, and the autoboot process will then erroneously consider the trunk device to be an autoboot device. Fix by recording the VLAN tag along with the MAC address, and treating the VLAN tag as part of the filter used to match the MAC address against candidate network devices. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/efi/efi_autoboot.h3
-rw-r--r--src/include/usr/autoboot.h3
-rw-r--r--src/interface/efi/efi_autoboot.c14
-rw-r--r--src/interface/efi/efiprefix.c2
-rw-r--r--src/usr/autoboot.c16
5 files changed, 30 insertions, 8 deletions
diff --git a/src/include/ipxe/efi/efi_autoboot.h b/src/include/ipxe/efi/efi_autoboot.h
index 706885e2..94fd2d76 100644
--- a/src/include/ipxe/efi/efi_autoboot.h
+++ b/src/include/ipxe/efi/efi_autoboot.h
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efi.h>
-extern int efi_set_autoboot_ll_addr ( EFI_HANDLE device );
+extern int efi_set_autoboot_ll_addr ( EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *path );
#endif /* _IPXE_EFI_AUTOBOOT_H */
diff --git a/src/include/usr/autoboot.h b/src/include/usr/autoboot.h
index f88b8494..3719b824 100644
--- a/src/include/usr/autoboot.h
+++ b/src/include/usr/autoboot.h
@@ -28,7 +28,8 @@ enum uriboot_flags {
extern void set_autoboot_busloc ( unsigned int bus_type,
unsigned int location );
-extern void set_autoboot_ll_addr ( const void *ll_addr, size_t len );
+extern void set_autoboot_ll_addr ( const void *ll_addr, size_t len,
+ unsigned int vlan );
extern int uriboot ( struct uri *filename, struct uri **root_paths,
unsigned int root_path_count, int drive,
diff --git a/src/interface/efi/efi_autoboot.c b/src/interface/efi/efi_autoboot.c
index 08d67f76..ec7793cd 100644
--- a/src/interface/efi/efi_autoboot.c
+++ b/src/interface/efi/efi_autoboot.c
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <errno.h>
#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_path.h>
#include <ipxe/efi/efi_autoboot.h>
#include <ipxe/efi/Protocol/SimpleNetwork.h>
#include <usr/autoboot.h>
@@ -40,9 +41,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Identify autoboot device
*
* @v device Device handle
+ * @v path Device path
* @ret rc Return status code
*/
-int efi_set_autoboot_ll_addr ( EFI_HANDLE device ) {
+int efi_set_autoboot_ll_addr ( EFI_HANDLE device,
+ EFI_DEVICE_PATH_PROTOCOL *path ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
EFI_SIMPLE_NETWORK_PROTOCOL *snp;
@@ -50,6 +53,7 @@ int efi_set_autoboot_ll_addr ( EFI_HANDLE device ) {
} snp;
EFI_SIMPLE_NETWORK_MODE *mode;
EFI_STATUS efirc;
+ unsigned int vlan;
int rc;
/* Look for an SNP instance on the image's device handle */
@@ -66,10 +70,16 @@ int efi_set_autoboot_ll_addr ( EFI_HANDLE device ) {
/* Record autoboot device */
mode = snp.snp->Mode;
- set_autoboot_ll_addr ( &mode->CurrentAddress, mode->HwAddressSize );
+ vlan = efi_path_vlan ( path );
+ set_autoboot_ll_addr ( &mode->CurrentAddress, mode->HwAddressSize,
+ vlan );
DBGC ( device, "EFI %s found autoboot link-layer address:\n",
efi_handle_name ( device ) );
DBGC_HDA ( device, 0, &mode->CurrentAddress, mode->HwAddressSize );
+ if ( vlan ) {
+ DBGC ( device, "EFI %s found autoboot VLAN %d\n",
+ efi_handle_name ( device ), vlan );
+ }
/* Close protocol */
bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
diff --git a/src/interface/efi/efiprefix.c b/src/interface/efi/efiprefix.c
index 7286b3e0..bdc36d9b 100644
--- a/src/interface/efi/efiprefix.c
+++ b/src/interface/efi/efiprefix.c
@@ -81,7 +81,7 @@ static void efi_init_application ( void ) {
EFI_DEVICE_PATH_PROTOCOL *path = efi_loaded_image_path;
/* Identify autoboot device, if any */
- efi_set_autoboot_ll_addr ( device );
+ efi_set_autoboot_ll_addr ( device, path );
/* Store cached DHCP packet, if any */
efi_cachedhcp_record ( device, path );
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c
index 24043ae6..d1f25962 100644
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdio.h>
#include <errno.h>
#include <ipxe/netdevice.h>
+#include <ipxe/vlan.h>
#include <ipxe/dhcp.h>
#include <ipxe/settings.h>
#include <ipxe/image.h>
@@ -57,6 +58,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Link-layer address of preferred autoboot device, if known */
static uint8_t autoboot_ll_addr[MAX_LL_ADDR_LEN];
+/** VLAN tag of preferred autoboot device, if known */
+static unsigned int autoboot_vlan;
+
/** Device location of preferred autoboot device, if known */
static struct device_description autoboot_desc;
@@ -494,8 +498,9 @@ void set_autoboot_busloc ( unsigned int bus_type, unsigned int location ) {
*/
static int is_autoboot_ll_addr ( struct net_device *netdev ) {
- return ( memcmp ( netdev->ll_addr, autoboot_ll_addr,
- netdev->ll_protocol->ll_addr_len ) == 0 );
+ return ( ( memcmp ( netdev->ll_addr, autoboot_ll_addr,
+ netdev->ll_protocol->ll_addr_len ) == 0 ) &&
+ ( vlan_tag ( netdev ) == autoboot_vlan ) );
}
/**
@@ -503,14 +508,19 @@ static int is_autoboot_ll_addr ( struct net_device *netdev ) {
*
* @v ll_addr Link-layer address
* @v len Length of link-layer address
+ * @v vlan VLAN tag
*/
-void set_autoboot_ll_addr ( const void *ll_addr, size_t len ) {
+void set_autoboot_ll_addr ( const void *ll_addr, size_t len,
+ unsigned int vlan ) {
/* Record autoboot link-layer address (truncated if necessary) */
if ( len > sizeof ( autoboot_ll_addr ) )
len = sizeof ( autoboot_ll_addr );
memcpy ( autoboot_ll_addr, ll_addr, len );
+ /* Record autoboot VLAN tag */
+ autoboot_vlan = vlan;
+
/* Mark autoboot device as present */
is_autoboot_device = is_autoboot_ll_addr;
}