mac-address: Migrate mac-address setting script to correct package
This is specific to enterprise boards, so it should go in the BSP.
Change-Id: I09b9f5047618dd31e75fc3e76d82b81b1cdbe245
diff --git a/etc/runonce.d/10-set-mac-addresses b/etc/runonce.d/10-set-mac-addresses
new file mode 100755
index 0000000..893ebd4
--- /dev/null
+++ b/etc/runonce.d/10-set-mac-addresses
@@ -0,0 +1,152 @@
+#!/usr/bin/python2.7
+
+'''This script generates the wifi and bluetooth MAC addresses assigned to a
+board, given the MAC address of it's primary ethernet interface. It's primary
+purpose is to store the MAC addresses in files on the root filesystem after
+system first start because we cannot burn these addresses into the peripherals,
+other than the ethernet PHY.
+
+This script only works in the case where the MAC addresses have been allocated
+in a monotonically adjacent style for all devices, and that wifi/bluetooth
+follows the ethernet MAC in series.
+'''
+
+
+import struct
+import sys
+
+
+MAC_VENDOR_PREFIX_STR = '70:20:84'
+
+BD_ADDR_PATH = '/etc/bluetooth/.bt_nv.bin'
+WIFI_ADDR_PATH = '/lib/firmware/wlan/wlan_mac.bin'
+
+BD_NVITEM = 0x02
+BD_RDWR_PROT = 0x00
+BD_NVITEM_SIZE = 0x06
+BD_ADDR_HEADER_STRUCT = r'BBB'
+BD_ADDR_MAC_STRUCT = r'BBBBBB'
+
+WIFI_CONFIG_TEMPLATE = '''\
+Intf0MacAddress={0}
+END
+'''
+
+ETHERNET_DEVICE = 'eth0'
+
+
+def GenerateNextMac(mac_address_str):
+ '''Given a MAC address string, generate the next MAC address in sequence.
+
+ Note: this strips off the vendor prefix and increments as though the suffix
+ was an integer. If the device suffix rolls over, there is no error thrown or
+ any other checking done.
+
+ Parameters:
+ mac_address_str: string. Colon-separated six-octet hexidecimal MAC address.
+
+ Returns:
+ string. The next MAC address in the sequence.
+ '''
+ device_suffix = GetMacDeviceSuffixString(mac_address_str)
+ suffix_number = MacDeviceSuffixToNumber(device_suffix)
+ suffix_string = MacDeviceSuffixNumberToString(suffix_number + 1)
+ next_mac = MAC_VENDOR_PREFIX_STR + ':' + suffix_string
+ return next_mac
+
+
+def MacDeviceSuffixNumberToString(device_suffix_number):
+ '''Given a device suffix number, generate a colon-separated hexidecimal
+ representation.
+
+ Parameters:
+ device_suffix_number: integer. The number to convert into a MAC suffix.
+
+ Returns:
+ string. The colon-separated hexidecimal version of the number passed in.
+ '''
+ suffix_string = '%06x' % device_suffix_number
+ suffix_array = []
+
+ for idx in range(0, len(suffix_string), 2):
+ suffix_array.append(suffix_string[idx] + suffix_string[idx + 1])
+
+ return ':'.join(suffix_array)
+
+
+def MacDeviceSuffixToNumber(mac_suffix):
+ '''Converts a given a three-octet colon separated hexidecimal MAC device suffix
+ into an integer.'''
+ mac_array = mac_suffix.split(':')
+ flatmac = ''.join(mac_array)
+ return int(flatmac, 16)
+
+
+def GetMacDeviceSuffixString(mac_address):
+ '''Strip the vendor prefix from a given a full six-octet colon separated
+ hexidecimal MAC.'''
+ mac_array = mac_address.split(':')
+ return ':'.join(mac_array[3:])
+
+
+def FindEthernetMacString(device):
+ '''Returns the MAC address string for a given network device from sysfs.
+
+ If an error occurs attempting to read from sysfs, or runs into an EOF
+ prematurely, returns None.
+ '''
+ sysfs_path = '/sys/class/net/%s/address' % (device)
+
+ try:
+ with open(sysfs_path, 'r') as fp:
+ address = fp.readline()
+ if len(address) == 0:
+ return None
+ address = address[:-1]
+ return address
+ except Exception as e:
+ print('Error reading %s: %s' % (sysfs_path, e))
+ return None
+
+
+def WriteWifiMacAddress(next_mac):
+ '''Writes the given MAC address string to the wifi configuration files.'''
+ try:
+ with open(WIFI_ADDR_PATH, 'w') as fp:
+ fp.write(WIFI_CONFIG_TEMPLATE.format(next_mac.translate(None, ':')))
+ return True
+ except Exception as e:
+ print('Error writing wifi configuration to %s: %s' % (WIFI_ADDR_PATH, e))
+ return False
+
+
+def WriteBluetoothMacAddress(next_mac):
+ '''Writes the given MAC address string to a binary file readable by Bluez.'''
+ mac_bytes = [int(x, 16) for x in next_mac.split(':')]
+
+ try:
+ with open(BD_ADDR_PATH, 'w') as fp:
+ fp.write(struct.pack(BD_ADDR_HEADER_STRUCT, BD_NVITEM, BD_RDWR_PROT,
+ BD_NVITEM_SIZE))
+ fp.write(struct.pack(BD_ADDR_MAC_STRUCT, *mac_bytes))
+ return True
+ except Exception as e:
+ print('Error writing bluetooth configuration to %s: %s' % (BD_ADDR_PATH, e))
+
+
+def Main():
+ base_mac_address = FindEthernetMacString(ETHERNET_DEVICE)
+
+ if base_mac_address == None:
+ sys.stderr.write('Unable to find MAC address for device %s\n' % (ETHERNET_DEVICE))
+ sys.exit(1)
+
+ next_mac = GenerateNextMac(base_mac_address)
+ print('Wifi/Bt MAC address will be %s' % next_mac)
+
+ WriteWifiMacAddress(next_mac)
+ WriteBluetoothMacAddress(next_mac)
+
+
+if __name__ == '__main__':
+ Main()