| /* |
| * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER ); |
| |
| #include <string.h> |
| #include <errno.h> |
| #include <byteswap.h> |
| #include <gpxe/dhcp.h> |
| #include <gpxe/settings.h> |
| #include <gpxe/device.h> |
| #include <gpxe/netdevice.h> |
| |
| /** @file |
| * |
| * Network device configuration settings |
| * |
| */ |
| |
| /** Network device named settings */ |
| struct setting mac_setting __setting = { |
| .name = "mac", |
| .description = "MAC address", |
| .type = &setting_type_hex, |
| }; |
| struct setting busid_setting __setting = { |
| .name = "busid", |
| .description = "Bus ID", |
| .type = &setting_type_hex, |
| }; |
| |
| /** |
| * Store value of network device setting |
| * |
| * @v settings Settings block |
| * @v setting Setting to store |
| * @v data Setting data, or NULL to clear setting |
| * @v len Length of setting data |
| * @ret rc Return status code |
| */ |
| static int netdev_store ( struct settings *settings, struct setting *setting, |
| const void *data, size_t len ) { |
| struct net_device *netdev = container_of ( settings, struct net_device, |
| settings.settings ); |
| |
| if ( setting_cmp ( setting, &mac_setting ) == 0 ) { |
| if ( len != netdev->ll_protocol->ll_addr_len ) |
| return -EINVAL; |
| memcpy ( netdev->ll_addr, data, len ); |
| return 0; |
| } |
| |
| return generic_settings_store ( settings, setting, data, len ); |
| } |
| |
| /** |
| * Fetch value of network device setting |
| * |
| * @v settings Settings block |
| * @v setting Setting to fetch |
| * @v data Setting data, or NULL to clear setting |
| * @v len Length of setting data |
| * @ret rc Return status code |
| */ |
| static int netdev_fetch ( struct settings *settings, struct setting *setting, |
| void *data, size_t len ) { |
| struct net_device *netdev = container_of ( settings, struct net_device, |
| settings.settings ); |
| struct device_description *desc = &netdev->dev->desc; |
| struct dhcp_netdev_desc dhcp_desc; |
| |
| if ( setting_cmp ( setting, &mac_setting ) == 0 ) { |
| if ( len > netdev->ll_protocol->ll_addr_len ) |
| len = netdev->ll_protocol->ll_addr_len; |
| memcpy ( data, netdev->ll_addr, len ); |
| return netdev->ll_protocol->ll_addr_len; |
| } |
| if ( setting_cmp ( setting, &busid_setting ) == 0 ) { |
| dhcp_desc.type = desc->bus_type; |
| dhcp_desc.vendor = htons ( desc->vendor ); |
| dhcp_desc.device = htons ( desc->device ); |
| if ( len > sizeof ( dhcp_desc ) ) |
| len = sizeof ( dhcp_desc ); |
| memcpy ( data, &dhcp_desc, len ); |
| return sizeof ( dhcp_desc ); |
| } |
| |
| return generic_settings_fetch ( settings, setting, data, len ); |
| } |
| |
| /** |
| * Clear network device settings |
| * |
| * @v settings Settings block |
| */ |
| static void netdev_clear ( struct settings *settings ) { |
| generic_settings_clear ( settings ); |
| } |
| |
| /** Network device configuration settings operations */ |
| struct settings_operations netdev_settings_operations = { |
| .store = netdev_store, |
| .fetch = netdev_fetch, |
| .clear = netdev_clear, |
| }; |