2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER );
25 #include <ipxe/dhcp.h>
26 #include <ipxe/dhcpopts.h>
27 #include <ipxe/settings.h>
28 #include <ipxe/device.h>
29 #include <ipxe/netdevice.h>
30 #include <ipxe/init.h>
34 * Network device configuration settings
38 /** Network device predefined settings */
39 const struct setting mac_setting __setting ( SETTING_NETDEV, mac ) = {
41 .description = "MAC address",
42 .type = &setting_type_hex,
44 const struct setting bustype_setting __setting ( SETTING_NETDEV, bustype ) = {
46 .description = "Bus type",
47 .type = &setting_type_string,
49 const struct setting busloc_setting __setting ( SETTING_NETDEV, busloc ) = {
51 .description = "Bus location",
52 .type = &setting_type_uint32,
54 const struct setting busid_setting __setting ( SETTING_NETDEV, busid ) = {
56 .description = "Bus ID",
57 .type = &setting_type_hex,
59 const struct setting chip_setting __setting ( SETTING_NETDEV, chip ) = {
61 .description = "Chip",
62 .type = &setting_type_string,
66 * Store MAC address setting
68 * @v netdev Network device
69 * @v data Setting data, or NULL to clear setting
70 * @v len Length of setting data
71 * @ret rc Return status code
73 static int netdev_store_mac ( struct net_device *netdev,
74 const void *data, size_t len ) {
75 struct ll_protocol *ll_protocol = netdev->ll_protocol;
77 /* Record new MAC address */
79 if ( len != netdev->ll_protocol->ll_addr_len )
81 memcpy ( netdev->ll_addr, data, len );
83 /* Reset MAC address if clearing setting */
84 ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
91 * Fetch MAC address setting
93 * @v netdev Network device
94 * @v data Buffer to fill with setting data
95 * @v len Length of buffer
96 * @ret len Length of setting data, or negative error
98 static int netdev_fetch_mac ( struct net_device *netdev, void *data,
101 if ( len > netdev->ll_protocol->ll_addr_len )
102 len = netdev->ll_protocol->ll_addr_len;
103 memcpy ( data, netdev->ll_addr, len );
104 return netdev->ll_protocol->ll_addr_len;
108 * Fetch bus type setting
110 * @v netdev Network device
111 * @v data Buffer to fill with setting data
112 * @v len Length of buffer
113 * @ret len Length of setting data, or negative error
115 static int netdev_fetch_bustype ( struct net_device *netdev, void *data,
117 static const char *bustypes[] = {
118 [BUS_TYPE_PCI] = "PCI",
119 [BUS_TYPE_ISAPNP] = "ISAPNP",
120 [BUS_TYPE_EISA] = "EISA",
121 [BUS_TYPE_MCA] = "MCA",
122 [BUS_TYPE_ISA] = "ISA",
123 [BUS_TYPE_TAP] = "TAP",
125 struct device_description *desc = &netdev->dev->desc;
128 assert ( desc->bus_type < ( sizeof ( bustypes ) /
129 sizeof ( bustypes[0] ) ) );
130 bustype = bustypes[desc->bus_type];
131 assert ( bustype != NULL );
132 strncpy ( data, bustype, len );
133 return strlen ( bustype );
137 * Fetch bus location setting
139 * @v netdev Network device
140 * @v data Buffer to fill with setting data
141 * @v len Length of buffer
142 * @ret len Length of setting data, or negative error
144 static int netdev_fetch_busloc ( struct net_device *netdev, void *data,
146 struct device_description *desc = &netdev->dev->desc;
149 busloc = cpu_to_be32 ( desc->location );
150 if ( len > sizeof ( busloc ) )
151 len = sizeof ( busloc );
152 memcpy ( data, &busloc, len );
153 return sizeof ( busloc );
157 * Fetch bus ID setting
159 * @v netdev Network device
160 * @v data Buffer to fill with setting data
161 * @v len Length of buffer
162 * @ret len Length of setting data, or negative error
164 static int netdev_fetch_busid ( struct net_device *netdev, void *data,
166 struct device_description *desc = &netdev->dev->desc;
167 struct dhcp_netdev_desc dhcp_desc;
169 dhcp_desc.type = desc->bus_type;
170 dhcp_desc.vendor = htons ( desc->vendor );
171 dhcp_desc.device = htons ( desc->device );
172 if ( len > sizeof ( dhcp_desc ) )
173 len = sizeof ( dhcp_desc );
174 memcpy ( data, &dhcp_desc, len );
175 return sizeof ( dhcp_desc );
181 * @v netdev Network device
182 * @v data Buffer to fill with setting data
183 * @v len Length of buffer
184 * @ret len Length of setting data, or negative error
186 static int netdev_fetch_chip ( struct net_device *netdev, void *data,
188 const char *chip = netdev->dev->driver_name;
190 strncpy ( data, chip, len );
191 return strlen ( chip );
194 /** A network device setting operation */
195 struct netdev_setting_operation {
197 const struct setting *setting;
198 /** Store setting (or NULL if not supported)
200 * @v netdev Network device
201 * @v data Setting data, or NULL to clear setting
202 * @v len Length of setting data
203 * @ret rc Return status code
205 int ( * store ) ( struct net_device *netdev, const void *data,
209 * @v netdev Network device
210 * @v data Buffer to fill with setting data
211 * @v len Length of buffer
212 * @ret len Length of setting data, or negative error
214 int ( * fetch ) ( struct net_device *netdev, void *data, size_t len );
217 /** Network device settings */
218 static struct netdev_setting_operation netdev_setting_operations[] = {
219 { &mac_setting, netdev_store_mac, netdev_fetch_mac },
220 { &bustype_setting, NULL, netdev_fetch_bustype },
221 { &busloc_setting, NULL, netdev_fetch_busloc },
222 { &busid_setting, NULL, netdev_fetch_busid },
223 { &chip_setting, NULL, netdev_fetch_chip },
227 * Store value of network device setting
229 * @v settings Settings block
230 * @v setting Setting to store
231 * @v data Setting data, or NULL to clear setting
232 * @v len Length of setting data
233 * @ret rc Return status code
235 static int netdev_store ( struct settings *settings,
236 const struct setting *setting,
237 const void *data, size_t len ) {
238 struct net_device *netdev = container_of ( settings, struct net_device,
240 struct netdev_setting_operation *op;
243 /* Handle network device-specific settings */
244 for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
245 sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
246 op = &netdev_setting_operations[i];
247 if ( setting_cmp ( setting, op->setting ) == 0 ) {
249 return op->store ( netdev, data, len );
256 return generic_settings_store ( settings, setting, data, len );
260 * Fetch value of network device setting
262 * @v settings Settings block
263 * @v setting Setting to fetch
264 * @v data Buffer to fill with setting data
265 * @v len Length of buffer
266 * @ret len Length of setting data, or negative error
268 static int netdev_fetch ( struct settings *settings, struct setting *setting,
269 void *data, size_t len ) {
270 struct net_device *netdev = container_of ( settings, struct net_device,
272 struct netdev_setting_operation *op;
275 /* Handle network device-specific settings */
276 for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
277 sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
278 op = &netdev_setting_operations[i];
279 if ( setting_cmp ( setting, op->setting ) == 0 )
280 return op->fetch ( netdev, data, len );
283 return generic_settings_fetch ( settings, setting, data, len );
287 * Clear network device settings
289 * @v settings Settings block
291 static void netdev_clear ( struct settings *settings ) {
292 generic_settings_clear ( settings );
295 /** Network device configuration settings operations */
296 struct settings_operations netdev_settings_operations = {
297 .store = netdev_store,
298 .fetch = netdev_fetch,
299 .clear = netdev_clear,
303 * Redirect "netX" settings block
305 * @v settings Settings block
306 * @ret settings Underlying settings block
308 static struct settings * netdev_redirect ( struct settings *settings ) {
309 struct net_device *netdev;
311 /* Redirect to most recently opened network device */
312 netdev = last_opened_netdev();
314 return netdev_settings ( netdev );
320 /** "netX" settings operations */
321 static struct settings_operations netdev_redirect_settings_operations = {
322 .redirect = netdev_redirect,
325 /** "netX" settings */
326 static struct settings netdev_redirect_settings = {
328 .siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
329 .children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
330 .op = &netdev_redirect_settings_operations,
333 /** Initialise "netX" settings */
334 static void netdev_redirect_settings_init ( void ) {
337 if ( ( rc = register_settings ( &netdev_redirect_settings, NULL,
339 DBG ( "Could not register netX settings: %s\n",
345 /** "netX" settings initialiser */
346 struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
347 .initialise = netdev_redirect_settings_init,