These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / net / netdev_settings.c
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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
17  * 02110-1301, USA.
18  *
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.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <string.h>
27 #include <errno.h>
28 #include <byteswap.h>
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>
35
36 /** @file
37  *
38  * Network device configuration settings
39  *
40  */
41
42 /** Network device predefined settings */
43 const struct setting mac_setting __setting ( SETTING_NETDEV, mac ) = {
44         .name = "mac",
45         .description = "MAC address",
46         .type = &setting_type_hex,
47 };
48 const struct setting bustype_setting __setting ( SETTING_NETDEV, bustype ) = {
49         .name = "bustype",
50         .description = "Bus type",
51         .type = &setting_type_string,
52 };
53 const struct setting busloc_setting __setting ( SETTING_NETDEV, busloc ) = {
54         .name = "busloc",
55         .description = "Bus location",
56         .type = &setting_type_uint32,
57 };
58 const struct setting busid_setting __setting ( SETTING_NETDEV, busid ) = {
59         .name = "busid",
60         .description = "Bus ID",
61         .type = &setting_type_hex,
62 };
63 const struct setting chip_setting __setting ( SETTING_NETDEV, chip ) = {
64         .name = "chip",
65         .description = "Chip",
66         .type = &setting_type_string,
67 };
68
69 /**
70  * Store MAC address setting
71  *
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
76  */
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;
80
81         /* Record new MAC address */
82         if ( data ) {
83                 if ( len != netdev->ll_protocol->ll_addr_len )
84                         return -EINVAL;
85                 memcpy ( netdev->ll_addr, data, len );
86         } else {
87                 /* Reset MAC address if clearing setting */
88                 ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
89         }
90
91         return 0;
92 }
93
94 /**
95  * Fetch MAC address setting
96  *
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
101  */
102 static int netdev_fetch_mac ( struct net_device *netdev, void *data,
103                               size_t len ) {
104
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;
109 }
110
111 /**
112  * Fetch bus type setting
113  *
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
118  */
119 static int netdev_fetch_bustype ( struct net_device *netdev, void *data,
120                                   size_t len ) {
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",
132         };
133         struct device_description *desc = &netdev->dev->desc;
134         const char *bustype;
135
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 );
142 }
143
144 /**
145  * Fetch bus location setting
146  *
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
151  */
152 static int netdev_fetch_busloc ( struct net_device *netdev, void *data,
153                                  size_t len ) {
154         struct device_description *desc = &netdev->dev->desc;
155         uint32_t busloc;
156
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 );
162 }
163
164 /**
165  * Fetch bus ID setting
166  *
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
171  */
172 static int netdev_fetch_busid ( struct net_device *netdev, void *data,
173                                 size_t len ) {
174         struct device_description *desc = &netdev->dev->desc;
175         struct dhcp_netdev_desc dhcp_desc;
176
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 );
184 }
185
186 /**
187  * Fetch chip setting
188  *
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
193  */
194 static int netdev_fetch_chip ( struct net_device *netdev, void *data,
195                                size_t len ) {
196         const char *chip = netdev->dev->driver_name;
197
198         strncpy ( data, chip, len );
199         return strlen ( chip );
200 }
201
202 /** A network device setting operation */
203 struct netdev_setting_operation {
204         /** Setting */
205         const struct setting *setting;
206         /** Store setting (or NULL if not supported)
207          *
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
212          */
213         int ( * store ) ( struct net_device *netdev, const void *data,
214                           size_t len );
215         /** Fetch setting
216          *
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
221          */
222         int ( * fetch ) ( struct net_device *netdev, void *data, size_t len );
223 };
224
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 },
232 };
233
234 /**
235  * Store value of network device setting
236  *
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
242  */
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,
247                                                    settings.settings );
248         struct netdev_setting_operation *op;
249         unsigned int i;
250
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 ) {
256                         if ( op->store ) {
257                                 return op->store ( netdev, data, len );
258                         } else {
259                                 return -ENOTSUP;
260                         }
261                 }
262         }
263
264         return generic_settings_store ( settings, setting, data, len );
265 }
266
267 /**
268  * Fetch value of network device setting
269  *
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
275  */
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,
279                                                    settings.settings );
280         struct netdev_setting_operation *op;
281         unsigned int i;
282
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 );
289         }
290
291         return generic_settings_fetch ( settings, setting, data, len );
292 }
293
294 /**
295  * Clear network device settings
296  *
297  * @v settings          Settings block
298  */
299 static void netdev_clear ( struct settings *settings ) {
300         generic_settings_clear ( settings );
301 }
302
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,
308 };
309
310 /**
311  * Redirect "netX" settings block
312  *
313  * @v settings          Settings block
314  * @ret settings        Underlying settings block
315  */
316 static struct settings * netdev_redirect ( struct settings *settings ) {
317         struct net_device *netdev;
318
319         /* Redirect to most recently opened network device */
320         netdev = last_opened_netdev();
321         if ( netdev ) {
322                 return netdev_settings ( netdev );
323         } else {
324                 return settings;
325         }
326 }
327
328 /** "netX" settings operations */
329 static struct settings_operations netdev_redirect_settings_operations = {
330         .redirect = netdev_redirect,
331 };
332
333 /** "netX" settings */
334 static struct settings netdev_redirect_settings = {
335         .refcnt = NULL,
336         .siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
337         .children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
338         .op = &netdev_redirect_settings_operations,
339 };
340
341 /** Initialise "netX" settings */
342 static void netdev_redirect_settings_init ( void ) {
343         int rc;
344
345         if ( ( rc = register_settings ( &netdev_redirect_settings, NULL,
346                                         "netX" ) ) != 0 ) {
347                 DBG ( "Could not register netX settings: %s\n",
348                       strerror ( rc ) );
349                 return;
350         }
351 }
352
353 /** "netX" settings initialiser */
354 struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
355         .initialise = netdev_redirect_settings_init,
356 };