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
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
29 #include <ipxe/dhcp.h>
30 #include <ipxe/dhcpopts.h>
31 #include <ipxe/settings.h>
32 #include <ipxe/device.h>
33 #include <ipxe/netdevice.h>
34 #include <ipxe/init.h>
38 * Network device configuration settings
42 /** Network device predefined settings */
43 const struct setting mac_setting
__setting ( SETTING_NETDEV
, mac
) = {
45 .description
= "MAC address",
46 .type
= &setting_type_hex
,
48 const struct setting bustype_setting
__setting ( SETTING_NETDEV
, bustype
) = {
50 .description
= "Bus type",
51 .type
= &setting_type_string
,
53 const struct setting busloc_setting
__setting ( SETTING_NETDEV
, busloc
) = {
55 .description
= "Bus location",
56 .type
= &setting_type_uint32
,
58 const struct setting busid_setting
__setting ( SETTING_NETDEV
, busid
) = {
60 .description
= "Bus ID",
61 .type
= &setting_type_hex
,
63 const struct setting chip_setting
__setting ( SETTING_NETDEV
, chip
) = {
65 .description
= "Chip",
66 .type
= &setting_type_string
,
70 * Store MAC address setting
72 * @v netdev Network device
73 * @v data Setting data, or NULL to clear setting
74 * @v len Length of setting data
75 * @ret rc Return status code
77 static int netdev_store_mac ( struct net_device
*netdev
,
78 const void *data
, size_t len
) {
79 struct ll_protocol
*ll_protocol
= netdev
->ll_protocol
;
81 /* Record new MAC address */
83 if ( len
!= netdev
->ll_protocol
->ll_addr_len
)
85 memcpy ( netdev
->ll_addr
, data
, len
);
87 /* Reset MAC address if clearing setting */
88 ll_protocol
->init_addr ( netdev
->hw_addr
, netdev
->ll_addr
);
95 * Fetch MAC address setting
97 * @v netdev Network device
98 * @v data Buffer to fill with setting data
99 * @v len Length of buffer
100 * @ret len Length of setting data, or negative error
102 static int netdev_fetch_mac ( struct net_device
*netdev
, void *data
,
105 if ( len
> netdev
->ll_protocol
->ll_addr_len
)
106 len
= netdev
->ll_protocol
->ll_addr_len
;
107 memcpy ( data
, netdev
->ll_addr
, len
);
108 return netdev
->ll_protocol
->ll_addr_len
;
112 * Fetch bus type setting
114 * @v netdev Network device
115 * @v data Buffer to fill with setting data
116 * @v len Length of buffer
117 * @ret len Length of setting data, or negative error
119 static int netdev_fetch_bustype ( struct net_device
*netdev
, void *data
,
121 static const char *bustypes
[] = {
122 [BUS_TYPE_PCI
] = "PCI",
123 [BUS_TYPE_ISAPNP
] = "ISAPNP",
124 [BUS_TYPE_EISA
] = "EISA",
125 [BUS_TYPE_MCA
] = "MCA",
126 [BUS_TYPE_ISA
] = "ISA",
127 [BUS_TYPE_TAP
] = "TAP",
128 [BUS_TYPE_EFI
] = "EFI",
129 [BUS_TYPE_XEN
] = "XEN",
130 [BUS_TYPE_HV
] = "HV",
131 [BUS_TYPE_USB
] = "USB",
133 struct device_description
*desc
= &netdev
->dev
->desc
;
136 assert ( desc
->bus_type
< ( sizeof ( bustypes
) /
137 sizeof ( bustypes
[0] ) ) );
138 bustype
= bustypes
[desc
->bus_type
];
139 assert ( bustype
!= NULL
);
140 strncpy ( data
, bustype
, len
);
141 return strlen ( bustype
);
145 * Fetch bus location setting
147 * @v netdev Network device
148 * @v data Buffer to fill with setting data
149 * @v len Length of buffer
150 * @ret len Length of setting data, or negative error
152 static int netdev_fetch_busloc ( struct net_device
*netdev
, void *data
,
154 struct device_description
*desc
= &netdev
->dev
->desc
;
157 busloc
= cpu_to_be32 ( desc
->location
);
158 if ( len
> sizeof ( busloc
) )
159 len
= sizeof ( busloc
);
160 memcpy ( data
, &busloc
, len
);
161 return sizeof ( busloc
);
165 * Fetch bus ID setting
167 * @v netdev Network device
168 * @v data Buffer to fill with setting data
169 * @v len Length of buffer
170 * @ret len Length of setting data, or negative error
172 static int netdev_fetch_busid ( struct net_device
*netdev
, void *data
,
174 struct device_description
*desc
= &netdev
->dev
->desc
;
175 struct dhcp_netdev_desc dhcp_desc
;
177 dhcp_desc
.type
= desc
->bus_type
;
178 dhcp_desc
.vendor
= htons ( desc
->vendor
);
179 dhcp_desc
.device
= htons ( desc
->device
);
180 if ( len
> sizeof ( dhcp_desc
) )
181 len
= sizeof ( dhcp_desc
);
182 memcpy ( data
, &dhcp_desc
, len
);
183 return sizeof ( dhcp_desc
);
189 * @v netdev Network device
190 * @v data Buffer to fill with setting data
191 * @v len Length of buffer
192 * @ret len Length of setting data, or negative error
194 static int netdev_fetch_chip ( struct net_device
*netdev
, void *data
,
196 const char *chip
= netdev
->dev
->driver_name
;
198 strncpy ( data
, chip
, len
);
199 return strlen ( chip
);
202 /** A network device setting operation */
203 struct netdev_setting_operation
{
205 const struct setting
*setting
;
206 /** Store setting (or NULL if not supported)
208 * @v netdev Network device
209 * @v data Setting data, or NULL to clear setting
210 * @v len Length of setting data
211 * @ret rc Return status code
213 int ( * store
) ( struct net_device
*netdev
, const void *data
,
217 * @v netdev Network device
218 * @v data Buffer to fill with setting data
219 * @v len Length of buffer
220 * @ret len Length of setting data, or negative error
222 int ( * fetch
) ( struct net_device
*netdev
, void *data
, size_t len
);
225 /** Network device settings */
226 static struct netdev_setting_operation netdev_setting_operations
[] = {
227 { &mac_setting
, netdev_store_mac
, netdev_fetch_mac
},
228 { &bustype_setting
, NULL
, netdev_fetch_bustype
},
229 { &busloc_setting
, NULL
, netdev_fetch_busloc
},
230 { &busid_setting
, NULL
, netdev_fetch_busid
},
231 { &chip_setting
, NULL
, netdev_fetch_chip
},
235 * Store value of network device setting
237 * @v settings Settings block
238 * @v setting Setting to store
239 * @v data Setting data, or NULL to clear setting
240 * @v len Length of setting data
241 * @ret rc Return status code
243 static int netdev_store ( struct settings
*settings
,
244 const struct setting
*setting
,
245 const void *data
, size_t len
) {
246 struct net_device
*netdev
= container_of ( settings
, struct net_device
,
248 struct netdev_setting_operation
*op
;
251 /* Handle network device-specific settings */
252 for ( i
= 0 ; i
< ( sizeof ( netdev_setting_operations
) /
253 sizeof ( netdev_setting_operations
[0] ) ) ; i
++ ) {
254 op
= &netdev_setting_operations
[i
];
255 if ( setting_cmp ( setting
, op
->setting
) == 0 ) {
257 return op
->store ( netdev
, data
, len
);
264 return generic_settings_store ( settings
, setting
, data
, len
);
268 * Fetch value of network device setting
270 * @v settings Settings block
271 * @v setting Setting to fetch
272 * @v data Buffer to fill with setting data
273 * @v len Length of buffer
274 * @ret len Length of setting data, or negative error
276 static int netdev_fetch ( struct settings
*settings
, struct setting
*setting
,
277 void *data
, size_t len
) {
278 struct net_device
*netdev
= container_of ( settings
, struct net_device
,
280 struct netdev_setting_operation
*op
;
283 /* Handle network device-specific settings */
284 for ( i
= 0 ; i
< ( sizeof ( netdev_setting_operations
) /
285 sizeof ( netdev_setting_operations
[0] ) ) ; i
++ ) {
286 op
= &netdev_setting_operations
[i
];
287 if ( setting_cmp ( setting
, op
->setting
) == 0 )
288 return op
->fetch ( netdev
, data
, len
);
291 return generic_settings_fetch ( settings
, setting
, data
, len
);
295 * Clear network device settings
297 * @v settings Settings block
299 static void netdev_clear ( struct settings
*settings
) {
300 generic_settings_clear ( settings
);
303 /** Network device configuration settings operations */
304 struct settings_operations netdev_settings_operations
= {
305 .store
= netdev_store
,
306 .fetch
= netdev_fetch
,
307 .clear
= netdev_clear
,
311 * Redirect "netX" settings block
313 * @v settings Settings block
314 * @ret settings Underlying settings block
316 static struct settings
* netdev_redirect ( struct settings
*settings
) {
317 struct net_device
*netdev
;
319 /* Redirect to most recently opened network device */
320 netdev
= last_opened_netdev();
322 return netdev_settings ( netdev
);
328 /** "netX" settings operations */
329 static struct settings_operations netdev_redirect_settings_operations
= {
330 .redirect
= netdev_redirect
,
333 /** "netX" settings */
334 static struct settings netdev_redirect_settings
= {
336 .siblings
= LIST_HEAD_INIT ( netdev_redirect_settings
.siblings
),
337 .children
= LIST_HEAD_INIT ( netdev_redirect_settings
.children
),
338 .op
= &netdev_redirect_settings_operations
,
341 /** Initialise "netX" settings */
342 static void netdev_redirect_settings_init ( void ) {
345 if ( ( rc
= register_settings ( &netdev_redirect_settings
, NULL
,
347 DBG ( "Could not register netX settings: %s\n",
353 /** "netX" settings initialiser */
354 struct init_fn netdev_redirect_settings_init_fn
__init_fn ( INIT_LATE
) = {
355 .initialise
= netdev_redirect_settings_init
,