Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / net / drivers / ieee1275 / ofnet.c
blob7e8e2a7446dfb9fce26925106c31675530431994
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2010,2011 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/net/netbuff.h>
20 #include <grub/ieee1275/ieee1275.h>
21 #include <grub/dl.h>
22 #include <grub/net.h>
23 #include <grub/time.h>
24 #include <grub/i18n.h>
26 GRUB_MOD_LICENSE ("GPLv3+");
28 struct grub_ofnetcard_data
30 char *path;
31 grub_ieee1275_ihandle_t handle;
34 static grub_err_t
35 card_open (struct grub_net_card *dev)
37 int status;
38 struct grub_ofnetcard_data *data = dev->data;
40 if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX))
42 char path[grub_strlen (data->path) +
43 sizeof (":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512")];
45 /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */
46 grub_snprintf (path, sizeof (path), "%s%s", data->path,
47 ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512");
48 status = grub_ieee1275_open (path, &(data->handle));
50 else
51 status = grub_ieee1275_open (data->path, &(data->handle));
53 if (status)
54 return grub_error (GRUB_ERR_IO, "Couldn't open network card.");
56 return GRUB_ERR_NONE;
59 static void
60 card_close (struct grub_net_card *dev)
62 struct grub_ofnetcard_data *data = dev->data;
64 if (data->handle)
65 grub_ieee1275_close (data->handle);
68 static grub_err_t
69 send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack)
71 grub_ssize_t actual;
72 int status;
73 struct grub_ofnetcard_data *data = dev->data;
74 grub_size_t len;
76 len = (pack->tail - pack->data);
77 if (len > dev->mtu)
78 len = dev->mtu;
80 grub_memcpy (dev->txbuf, pack->data, len);
81 status = grub_ieee1275_write (data->handle, dev->txbuf,
82 pack->tail - pack->data, &actual);
84 if (status)
85 return grub_error (GRUB_ERR_IO, N_("couldn't send network packet"));
86 return GRUB_ERR_NONE;
89 static struct grub_net_buff *
90 get_card_packet (struct grub_net_card *dev)
92 grub_ssize_t actual;
93 int rc;
94 struct grub_ofnetcard_data *data = dev->data;
95 grub_uint64_t start_time;
96 struct grub_net_buff *nb;
98 nb = grub_netbuff_alloc (dev->mtu + 64 + 2);
99 if (!nb)
101 grub_netbuff_free (nb);
102 return NULL;
104 /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
105 by 4. So that IP header is aligned on 4 bytes. */
106 grub_netbuff_reserve (nb, 2);
108 start_time = grub_get_time_ms ();
110 rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual);
111 while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
112 if (actual > 0)
114 grub_netbuff_put (nb, actual);
115 return nb;
117 grub_netbuff_free (nb);
118 return NULL;
121 static struct grub_net_card_driver ofdriver =
123 .name = "ofnet",
124 .open = card_open,
125 .close = card_close,
126 .send = send_card_buffer,
127 .recv = get_card_packet
130 static const struct
132 const char *name;
133 int offset;
136 bootp_response_properties[] =
138 { .name = "bootp-response", .offset = 0},
139 { .name = "dhcp-response", .offset = 0},
140 { .name = "bootpreply-packet", .offset = 0x2a},
143 static void
144 grub_ieee1275_net_config_real (const char *devpath, char **device, char **path)
146 struct grub_net_card *card;
148 /* FIXME: Check that it's the right card. */
149 FOR_NET_CARDS (card)
151 char *bootp_response;
152 char *cardpath;
153 char *canon;
155 grub_ssize_t size = -1;
156 unsigned int i;
158 if (card->driver != &ofdriver)
159 continue;
161 cardpath = ((struct grub_ofnetcard_data *) card->data)->path;
162 canon = grub_ieee1275_canonicalise_devname (cardpath);
163 if (grub_strcmp (devpath, canon) != 0)
165 grub_free (canon);
166 continue;
168 grub_free (canon);
170 for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
171 if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
172 bootp_response_properties[i].name,
173 &size) >= 0)
174 break;
176 if (size < 0)
177 return;
179 bootp_response = grub_malloc (size);
180 if (!bootp_response)
182 grub_print_error ();
183 return;
185 if (grub_ieee1275_get_property (grub_ieee1275_chosen,
186 bootp_response_properties[i].name,
187 bootp_response, size, 0) < 0)
188 return;
190 grub_net_configure_by_dhcp_ack (card->name, card, 0,
191 (struct grub_net_bootp_packet *)
192 (bootp_response
193 + bootp_response_properties[i].offset),
194 size - bootp_response_properties[i].offset,
195 1, device, path);
196 grub_free (bootp_response);
197 return;
201 static char *
202 find_alias (const char *fullname)
204 char *ret = NULL;
205 auto int find_alias_hook (struct grub_ieee1275_devalias *alias);
207 int find_alias_hook (struct grub_ieee1275_devalias *alias)
209 if (grub_strcmp (alias->path, fullname) == 0)
211 ret = grub_strdup (alias->name);
212 return 1;
214 return 0;
217 grub_devalias_iterate (find_alias_hook);
218 grub_errno = GRUB_ERR_NONE;
219 return ret;
222 static int
223 search_net_devices (struct grub_ieee1275_devalias *alias)
225 struct grub_ofnetcard_data *ofdata;
226 struct grub_net_card *card;
227 grub_ieee1275_phandle_t devhandle;
228 grub_net_link_level_address_t lla;
229 char *shortname;
231 if (grub_strcmp (alias->type, "network") != 0)
232 return 0;
234 ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data));
235 if (!ofdata)
237 grub_print_error ();
238 return 1;
240 card = grub_zalloc (sizeof (struct grub_net_card));
241 if (!card)
243 grub_free (ofdata);
244 grub_print_error ();
245 return 1;
248 ofdata->path = grub_strdup (alias->path);
250 grub_ieee1275_finddevice (ofdata->path, &devhandle);
253 grub_uint32_t t;
254 if (grub_ieee1275_get_integer_property (devhandle,
255 "max-frame-size", &t,
256 sizeof (t), 0))
257 card->mtu = 1500;
258 else
259 card->mtu = t;
262 if (grub_ieee1275_get_property (devhandle, "mac-address",
263 &(lla.mac), 6, 0)
264 && grub_ieee1275_get_property (devhandle, "local-mac-address",
265 &(lla.mac), 6, 0))
267 grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
268 grub_print_error ();
269 return 0;
272 lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
273 card->default_address = lla;
275 card->txbufsize = ALIGN_UP (card->mtu, 64) + 256;
277 if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
279 struct alloc_args
281 struct grub_ieee1275_common_hdr common;
282 grub_ieee1275_cell_t method;
283 grub_ieee1275_cell_t len;
284 grub_ieee1275_cell_t catch;
285 grub_ieee1275_cell_t result;
287 args;
288 INIT_IEEE1275_COMMON (&args.common, "interpret", 2, 2);
289 args.len = card->txbufsize;
290 args.method = (grub_ieee1275_cell_t) "alloc-mem";
292 if (IEEE1275_CALL_ENTRY_FN (&args) == -1
293 || args.catch)
295 card->txbuf = 0;
296 grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
298 else
299 card->txbuf = (void *) args.result;
301 else
302 card->txbuf = grub_zalloc (card->txbufsize);
303 if (!card->txbuf)
305 grub_print_error ();
306 return 0;
308 card->driver = NULL;
309 card->data = ofdata;
310 card->flags = 0;
311 shortname = find_alias (alias->path);
312 card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path);
313 card->idle_poll_delay_ms = 10;
314 grub_free (shortname);
316 card->driver = &ofdriver;
317 grub_net_card_register (card);
318 return 0;
321 static void
322 grub_ofnet_findcards (void)
324 /* Look at all nodes for devices of the type network. */
325 grub_ieee1275_devices_iterate (search_net_devices);
328 GRUB_MOD_INIT(ofnet)
330 grub_ofnet_findcards ();
331 grub_ieee1275_net_config = grub_ieee1275_net_config_real;
334 GRUB_MOD_FINI(ofnet)
336 struct grub_net_card *card, *next;
338 FOR_NET_CARDS_SAFE (card, next)
339 if (card->driver && grub_strcmp (card->driver->name, "ofnet") == 0)
340 grub_net_card_unregister (card);
341 grub_ieee1275_net_config = 0;