|
@@ -31,6 +31,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
31
|
31
|
#include <ipxe/usb.h>
|
32
|
32
|
#include <ipxe/usbnet.h>
|
33
|
33
|
#include <ipxe/profile.h>
|
|
34
|
+#include <ipxe/base16.h>
|
|
35
|
+#include <ipxe/smbios.h>
|
34
|
36
|
#include "smsc95xx.h"
|
35
|
37
|
|
36
|
38
|
/** @file
|
|
@@ -279,6 +281,111 @@ static int smsc95xx_fetch_mac_eeprom ( struct smsc95xx_device *smsc95xx,
|
279
|
281
|
return -ENODEV;
|
280
|
282
|
}
|
281
|
283
|
|
|
284
|
+ DBGC ( smsc95xx, "SMSC95XX %p using EEPROM MAC %s\n",
|
|
285
|
+ smsc95xx, eth_ntoa ( hw_addr ) );
|
|
286
|
+ return 0;
|
|
287
|
+}
|
|
288
|
+
|
|
289
|
+/**
|
|
290
|
+ * Construct MAC address for Honeywell VM3
|
|
291
|
+ *
|
|
292
|
+ * @v smsc95xx SMSC95xx device
|
|
293
|
+ * @v hw_addr Hardware address to fill in
|
|
294
|
+ * @ret rc Return status code
|
|
295
|
+ */
|
|
296
|
+static int smsc95xx_fetch_mac_vm3 ( struct smsc95xx_device *smsc95xx,
|
|
297
|
+ uint8_t *hw_addr ) {
|
|
298
|
+ struct smbios_structure structure;
|
|
299
|
+ struct smbios_system_information system;
|
|
300
|
+ struct {
|
|
301
|
+ char manufacturer[ 10 /* "Honeywell" + NUL */ ];
|
|
302
|
+ char product[ 4 /* "VM3" + NUL */ ];
|
|
303
|
+ char mac[ base16_encoded_len ( ETH_ALEN ) + 1 /* NUL */ ];
|
|
304
|
+ } strings;
|
|
305
|
+ int len;
|
|
306
|
+ int rc;
|
|
307
|
+
|
|
308
|
+ /* Find system information */
|
|
309
|
+ if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_SYSTEM_INFORMATION, 0,
|
|
310
|
+ &structure ) ) != 0 ) {
|
|
311
|
+ DBGC ( smsc95xx, "SMSC95XX %p could not find system "
|
|
312
|
+ "information: %s\n", smsc95xx, strerror ( rc ) );
|
|
313
|
+ return rc;
|
|
314
|
+ }
|
|
315
|
+
|
|
316
|
+ /* Read system information */
|
|
317
|
+ if ( ( rc = read_smbios_structure ( &structure, &system,
|
|
318
|
+ sizeof ( system ) ) ) != 0 ) {
|
|
319
|
+ DBGC ( smsc95xx, "SMSC95XX %p could not read system "
|
|
320
|
+ "information: %s\n", smsc95xx, strerror ( rc ) );
|
|
321
|
+ return rc;
|
|
322
|
+ }
|
|
323
|
+
|
|
324
|
+ /* NUL-terminate all strings to be fetched */
|
|
325
|
+ memset ( &strings, 0, sizeof ( strings ) );
|
|
326
|
+
|
|
327
|
+ /* Fetch system manufacturer name */
|
|
328
|
+ len = read_smbios_string ( &structure, system.manufacturer,
|
|
329
|
+ strings.manufacturer,
|
|
330
|
+ ( sizeof ( strings.manufacturer ) - 1 ) );
|
|
331
|
+ if ( len < 0 ) {
|
|
332
|
+ rc = len;
|
|
333
|
+ DBGC ( smsc95xx, "SMSC95XX %p could not read manufacturer "
|
|
334
|
+ "name: %s\n", smsc95xx, strerror ( rc ) );
|
|
335
|
+ return rc;
|
|
336
|
+ }
|
|
337
|
+
|
|
338
|
+ /* Fetch system product name */
|
|
339
|
+ len = read_smbios_string ( &structure, system.product, strings.product,
|
|
340
|
+ ( sizeof ( strings.product ) - 1 ) );
|
|
341
|
+ if ( len < 0 ) {
|
|
342
|
+ rc = len;
|
|
343
|
+ DBGC ( smsc95xx, "SMSC95XX %p could not read product name: "
|
|
344
|
+ "%s\n", smsc95xx, strerror ( rc ) );
|
|
345
|
+ return rc;
|
|
346
|
+ }
|
|
347
|
+
|
|
348
|
+ /* Ignore non-VM3 devices */
|
|
349
|
+ if ( ( strcmp ( strings.manufacturer, "Honeywell" ) != 0 ) ||
|
|
350
|
+ ( strcmp ( strings.product, "VM3" ) != 0 ) )
|
|
351
|
+ return -ENOTTY;
|
|
352
|
+
|
|
353
|
+ /* Find OEM strings */
|
|
354
|
+ if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_OEM_STRINGS, 0,
|
|
355
|
+ &structure ) ) != 0 ) {
|
|
356
|
+ DBGC ( smsc95xx, "SMSC95XX %p could not find OEM strings: %s\n",
|
|
357
|
+ smsc95xx, strerror ( rc ) );
|
|
358
|
+ return rc;
|
|
359
|
+ }
|
|
360
|
+
|
|
361
|
+ /* Fetch MAC address */
|
|
362
|
+ len = read_smbios_string ( &structure, SMSC95XX_VM3_OEM_STRING_MAC,
|
|
363
|
+ strings.mac, ( sizeof ( strings.mac ) - 1 ));
|
|
364
|
+ if ( len < 0 ) {
|
|
365
|
+ rc = len;
|
|
366
|
+ DBGC ( smsc95xx, "SMSC95XX %p could not read OEM string: %s\n",
|
|
367
|
+ smsc95xx, strerror ( rc ) );
|
|
368
|
+ return rc;
|
|
369
|
+ }
|
|
370
|
+
|
|
371
|
+ /* Sanity check */
|
|
372
|
+ if ( len != ( ( int ) ( sizeof ( strings.mac ) - 1 ) ) ) {
|
|
373
|
+ DBGC ( smsc95xx, "SMSC95XX %p invalid MAC address \"%s\"\n",
|
|
374
|
+ smsc95xx, strings.mac );
|
|
375
|
+ return -EINVAL;
|
|
376
|
+ }
|
|
377
|
+
|
|
378
|
+ /* Decode MAC address */
|
|
379
|
+ len = base16_decode ( strings.mac, hw_addr, ETH_ALEN );
|
|
380
|
+ if ( len < 0 ) {
|
|
381
|
+ rc = len;
|
|
382
|
+ DBGC ( smsc95xx, "SMSC95XX %p invalid MAC address \"%s\"\n",
|
|
383
|
+ smsc95xx, strings.mac );
|
|
384
|
+ return rc;
|
|
385
|
+ }
|
|
386
|
+
|
|
387
|
+ DBGC ( smsc95xx, "SMSC95XX %p using VM3 MAC %s\n",
|
|
388
|
+ smsc95xx, eth_ntoa ( hw_addr ) );
|
282
|
389
|
return 0;
|
283
|
390
|
}
|
284
|
391
|
|
|
@@ -297,8 +404,14 @@ static int smsc95xx_fetch_mac ( struct smsc95xx_device *smsc95xx,
|
297
|
404
|
if ( ( rc = smsc95xx_fetch_mac_eeprom ( smsc95xx, hw_addr ) ) == 0 )
|
298
|
405
|
return 0;
|
299
|
406
|
|
|
407
|
+ /* Construct MAC address for Honeywell VM3, if applicable */
|
|
408
|
+ if ( ( rc = smsc95xx_fetch_mac_vm3 ( smsc95xx, hw_addr ) ) == 0 )
|
|
409
|
+ return 0;
|
|
410
|
+
|
300
|
411
|
/* Otherwise, generate a random MAC address */
|
301
|
412
|
eth_random_addr ( hw_addr );
|
|
413
|
+ DBGC ( smsc95xx, "SMSC95XX %p using random MAC %s\n",
|
|
414
|
+ smsc95xx, eth_ntoa ( hw_addr ) );
|
302
|
415
|
return 0;
|
303
|
416
|
}
|
304
|
417
|
|