]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[smsc95xx] Fetch MAC from SMBIOS OEM string for Honeywell VM3
authorMichael Brown <mcb30@ipxe.org>
Wed, 23 Dec 2015 15:25:31 +0000 (15:25 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 4 Jan 2016 15:31:26 +0000 (15:31 +0000)
The Honeywell VM3 has no attached EEPROM, and records the MAC address
within an SMBIOS OEM string.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/smsc95xx.c
src/drivers/net/smsc95xx.h
src/include/ipxe/smbios.h

index e852e06f202c38231a97caa8a78c7cc6478d0a4a..c1dd08051137e4e871715531c4a0e09ef9cc8b8d 100644 (file)
@@ -31,6 +31,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/usb.h>
 #include <ipxe/usbnet.h>
 #include <ipxe/profile.h>
+#include <ipxe/base16.h>
+#include <ipxe/smbios.h>
 #include "smsc95xx.h"
 
 /** @file
@@ -279,6 +281,111 @@ static int smsc95xx_fetch_mac_eeprom ( struct smsc95xx_device *smsc95xx,
                return -ENODEV;
        }
 
+       DBGC ( smsc95xx, "SMSC95XX %p using EEPROM MAC %s\n",
+              smsc95xx, eth_ntoa ( hw_addr ) );
+       return 0;
+}
+
+/**
+ * Construct MAC address for Honeywell VM3
+ *
+ * @v smsc95xx         SMSC95xx device
+ * @v hw_addr          Hardware address to fill in
+ * @ret rc             Return status code
+ */
+static int smsc95xx_fetch_mac_vm3 ( struct smsc95xx_device *smsc95xx,
+                                   uint8_t *hw_addr ) {
+       struct smbios_structure structure;
+       struct smbios_system_information system;
+       struct {
+               char manufacturer[ 10 /* "Honeywell" + NUL */ ];
+               char product[ 4 /* "VM3" + NUL */ ];
+               char mac[ base16_encoded_len ( ETH_ALEN ) + 1 /* NUL */ ];
+       } strings;
+       int len;
+       int rc;
+
+       /* Find system information */
+       if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_SYSTEM_INFORMATION, 0,
+                                           &structure ) ) != 0 ) {
+               DBGC ( smsc95xx, "SMSC95XX %p could not find system "
+                      "information: %s\n", smsc95xx, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Read system information */
+       if ( ( rc = read_smbios_structure ( &structure, &system,
+                                           sizeof ( system ) ) ) != 0 ) {
+               DBGC ( smsc95xx, "SMSC95XX %p could not read system "
+                      "information: %s\n", smsc95xx, strerror ( rc ) );
+               return rc;
+       }
+
+       /* NUL-terminate all strings to be fetched */
+       memset ( &strings, 0, sizeof ( strings ) );
+
+       /* Fetch system manufacturer name */
+       len = read_smbios_string ( &structure, system.manufacturer,
+                                  strings.manufacturer,
+                                  ( sizeof ( strings.manufacturer ) - 1 ) );
+       if ( len < 0 ) {
+               rc = len;
+               DBGC ( smsc95xx, "SMSC95XX %p could not read manufacturer "
+                      "name: %s\n", smsc95xx, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Fetch system product name */
+       len = read_smbios_string ( &structure, system.product, strings.product,
+                                  ( sizeof ( strings.product ) - 1 ) );
+       if ( len < 0 ) {
+               rc = len;
+               DBGC ( smsc95xx, "SMSC95XX %p could not read product name: "
+                      "%s\n", smsc95xx, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Ignore non-VM3 devices */
+       if ( ( strcmp ( strings.manufacturer, "Honeywell" ) != 0 ) ||
+            ( strcmp ( strings.product, "VM3" ) != 0 ) )
+               return -ENOTTY;
+
+       /* Find OEM strings */
+       if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_OEM_STRINGS, 0,
+                                           &structure ) ) != 0 ) {
+               DBGC ( smsc95xx, "SMSC95XX %p could not find OEM strings: %s\n",
+                      smsc95xx, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Fetch MAC address */
+       len = read_smbios_string ( &structure, SMSC95XX_VM3_OEM_STRING_MAC,
+                                  strings.mac, ( sizeof ( strings.mac ) - 1 ));
+       if ( len < 0 ) {
+               rc = len;
+               DBGC ( smsc95xx, "SMSC95XX %p could not read OEM string: %s\n",
+                      smsc95xx, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Sanity check */
+       if ( len != ( ( int ) ( sizeof ( strings.mac ) - 1 ) ) ) {
+               DBGC ( smsc95xx, "SMSC95XX %p invalid MAC address \"%s\"\n",
+                      smsc95xx, strings.mac );
+               return -EINVAL;
+       }
+
+       /* Decode MAC address */
+       len = base16_decode ( strings.mac, hw_addr, ETH_ALEN );
+       if ( len < 0 ) {
+               rc = len;
+               DBGC ( smsc95xx, "SMSC95XX %p invalid MAC address \"%s\"\n",
+                      smsc95xx, strings.mac );
+               return rc;
+       }
+
+       DBGC ( smsc95xx, "SMSC95XX %p using VM3 MAC %s\n",
+              smsc95xx, eth_ntoa ( hw_addr ) );
        return 0;
 }
 
@@ -297,8 +404,14 @@ static int smsc95xx_fetch_mac ( struct smsc95xx_device *smsc95xx,
        if ( ( rc = smsc95xx_fetch_mac_eeprom ( smsc95xx, hw_addr ) ) == 0 )
                return 0;
 
+       /* Construct MAC address for Honeywell VM3, if applicable */
+       if ( ( rc = smsc95xx_fetch_mac_vm3 ( smsc95xx, hw_addr ) ) == 0 )
+               return 0;
+
        /* Otherwise, generate a random MAC address */
        eth_random_addr ( hw_addr );
+       DBGC ( smsc95xx, "SMSC95XX %p using random MAC %s\n",
+              smsc95xx, eth_ntoa ( hw_addr ) );
        return 0;
 }
 
index 3b83327bf0cb1a12b890c4654d130bd39511ef17..d66d8680360e66aca5c30ea4c75b714d7750c739 100644 (file)
@@ -251,4 +251,7 @@ struct smsc95xx_device {
          ETH_FRAME_LEN + 4 /* possible VLAN header */          \
          + 4 /* CRC */ )
 
+/** Honeywell VM3 MAC address OEM string index */
+#define SMSC95XX_VM3_OEM_STRING_MAC 2
+
 #endif /* _SMSC95XX_H */
index 24b05ed6225328c25b8c3a3b9ef9585d32626617..c1d8fea3e08fed5c13b72345532c240c86fd4b93 100644 (file)
@@ -152,6 +152,9 @@ struct smbios_enclosure_information {
 /** SMBIOS enclosure information structure type */
 #define SMBIOS_TYPE_ENCLOSURE_INFORMATION 3
 
+/** SMBIOS OEM strings structure type */
+#define SMBIOS_TYPE_OEM_STRINGS 11
+
 /**
  * SMBIOS entry point descriptor
  *