|  | @@ -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 |  
 |