Add qemu 2.4.0
[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
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <string.h>
23 #include <errno.h>
24 #include <byteswap.h>
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>
31
32 /** @file
33  *
34  * Network device configuration settings
35  *
36  */
37
38 /** Network device predefined settings */
39 const struct setting mac_setting __setting ( SETTING_NETDEV, mac ) = {
40         .name = "mac",
41         .description = "MAC address",
42         .type = &setting_type_hex,
43 };
44 const struct setting bustype_setting __setting ( SETTING_NETDEV, bustype ) = {
45         .name = "bustype",
46         .description = "Bus type",
47         .type = &setting_type_string,
48 };
49 const struct setting busloc_setting __setting ( SETTING_NETDEV, busloc ) = {
50         .name = "busloc",
51         .description = "Bus location",
52         .type = &setting_type_uint32,
53 };
54 const struct setting busid_setting __setting ( SETTING_NETDEV, busid ) = {
55         .name = "busid",
56         .description = "Bus ID",
57         .type = &setting_type_hex,
58 };
59 const struct setting chip_setting __setting ( SETTING_NETDEV, chip ) = {
60         .name = "chip",
61         .description = "Chip",
62         .type = &setting_type_string,
63 };
64
65 /**
66  * Store MAC address setting
67  *
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
72  */
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;
76
77         /* Record new MAC address */
78         if ( data ) {
79                 if ( len != netdev->ll_protocol->ll_addr_len )
80                         return -EINVAL;
81                 memcpy ( netdev->ll_addr, data, len );
82         } else {
83                 /* Reset MAC address if clearing setting */
84                 ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
85         }
86
87         return 0;
88 }
89
90 /**
91  * Fetch MAC address setting
92  *
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
97  */
98 static int netdev_fetch_mac ( struct net_device *netdev, void *data,
99                               size_t len ) {
100
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;
105 }
106
107 /**
108  * Fetch bus type setting
109  *
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
114  */
115 static int netdev_fetch_bustype ( struct net_device *netdev, void *data,
116                                   size_t len ) {
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",
124         };
125         struct device_description *desc = &netdev->dev->desc;
126         const char *bustype;
127
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 );
134 }
135
136 /**
137  * Fetch bus location setting
138  *
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
143  */
144 static int netdev_fetch_busloc ( struct net_device *netdev, void *data,
145                                  size_t len ) {
146         struct device_description *desc = &netdev->dev->desc;
147         uint32_t busloc;
148
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 );
154 }
155
156 /**
157  * Fetch bus ID setting
158  *
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
163  */
164 static int netdev_fetch_busid ( struct net_device *netdev, void *data,
165                                 size_t len ) {
166         struct device_description *desc = &netdev->dev->desc;
167         struct dhcp_netdev_desc dhcp_desc;
168
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 );
176 }
177
178 /**
179  * Fetch chip setting
180  *
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
185  */
186 static int netdev_fetch_chip ( struct net_device *netdev, void *data,
187                                size_t len ) {
188         const char *chip = netdev->dev->driver_name;
189
190         strncpy ( data, chip, len );
191         return strlen ( chip );
192 }
193
194 /** A network device setting operation */
195 struct netdev_setting_operation {
196         /** Setting */
197         const struct setting *setting;
198         /** Store setting (or NULL if not supported)
199          *
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
204          */
205         int ( * store ) ( struct net_device *netdev, const void *data,
206                           size_t len );
207         /** Fetch setting
208          *
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
213          */
214         int ( * fetch ) ( struct net_device *netdev, void *data, size_t len );
215 };
216
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 },
224 };
225
226 /**
227  * Store value of network device setting
228  *
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
234  */
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,
239                                                    settings.settings );
240         struct netdev_setting_operation *op;
241         unsigned int i;
242
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 ) {
248                         if ( op->store ) {
249                                 return op->store ( netdev, data, len );
250                         } else {
251                                 return -ENOTSUP;
252                         }
253                 }
254         }
255
256         return generic_settings_store ( settings, setting, data, len );
257 }
258
259 /**
260  * Fetch value of network device setting
261  *
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
267  */
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,
271                                                    settings.settings );
272         struct netdev_setting_operation *op;
273         unsigned int i;
274
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 );
281         }
282
283         return generic_settings_fetch ( settings, setting, data, len );
284 }
285
286 /**
287  * Clear network device settings
288  *
289  * @v settings          Settings block
290  */
291 static void netdev_clear ( struct settings *settings ) {
292         generic_settings_clear ( settings );
293 }
294
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,
300 };
301
302 /**
303  * Redirect "netX" settings block
304  *
305  * @v settings          Settings block
306  * @ret settings        Underlying settings block
307  */
308 static struct settings * netdev_redirect ( struct settings *settings ) {
309         struct net_device *netdev;
310
311         /* Redirect to most recently opened network device */
312         netdev = last_opened_netdev();
313         if ( netdev ) {
314                 return netdev_settings ( netdev );
315         } else {
316                 return settings;
317         }
318 }
319
320 /** "netX" settings operations */
321 static struct settings_operations netdev_redirect_settings_operations = {
322         .redirect = netdev_redirect,
323 };
324
325 /** "netX" settings */
326 static struct settings netdev_redirect_settings = {
327         .refcnt = NULL,
328         .siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
329         .children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
330         .op = &netdev_redirect_settings_operations,
331 };
332
333 /** Initialise "netX" settings */
334 static void netdev_redirect_settings_init ( void ) {
335         int rc;
336
337         if ( ( rc = register_settings ( &netdev_redirect_settings, NULL,
338                                         "netX" ) ) != 0 ) {
339                 DBG ( "Could not register netX settings: %s\n",
340                       strerror ( rc ) );
341                 return;
342         }
343 }
344
345 /** "netX" settings initialiser */
346 struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
347         .initialise = netdev_redirect_settings_init,
348 };