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>
23 #include <grub/time.h>
24 #include <grub/i18n.h>
26 GRUB_MOD_LICENSE ("GPLv3+");
28 struct grub_ofnetcard_data
31 grub_ieee1275_ihandle_t handle
;
35 card_open (struct grub_net_card
*dev
)
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
));
51 status
= grub_ieee1275_open (data
->path
, &(data
->handle
));
54 return grub_error (GRUB_ERR_IO
, "Couldn't open network card.");
60 card_close (struct grub_net_card
*dev
)
62 struct grub_ofnetcard_data
*data
= dev
->data
;
65 grub_ieee1275_close (data
->handle
);
69 send_card_buffer (struct grub_net_card
*dev
, struct grub_net_buff
*pack
)
73 struct grub_ofnetcard_data
*data
= dev
->data
;
76 len
= (pack
->tail
- pack
->data
);
80 grub_memcpy (dev
->txbuf
, pack
->data
, len
);
81 status
= grub_ieee1275_write (data
->handle
, dev
->txbuf
,
82 pack
->tail
- pack
->data
, &actual
);
85 return grub_error (GRUB_ERR_IO
, N_("couldn't send network packet"));
89 static struct grub_net_buff
*
90 get_card_packet (struct grub_net_card
*dev
)
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);
101 grub_netbuff_free (nb
);
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));
114 grub_netbuff_put (nb
, actual
);
117 grub_netbuff_free (nb
);
121 static struct grub_net_card_driver ofdriver
=
126 .send
= send_card_buffer
,
127 .recv
= get_card_packet
136 bootp_response_properties
[] =
138 { .name
= "bootp-response", .offset
= 0},
139 { .name
= "dhcp-response", .offset
= 0},
140 { .name
= "bootpreply-packet", .offset
= 0x2a},
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. */
151 char *bootp_response
;
155 grub_ssize_t size
= -1;
158 if (card
->driver
!= &ofdriver
)
161 cardpath
= ((struct grub_ofnetcard_data
*) card
->data
)->path
;
162 canon
= grub_ieee1275_canonicalise_devname (cardpath
);
163 if (grub_strcmp (devpath
, canon
) != 0)
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
,
179 bootp_response
= grub_malloc (size
);
185 if (grub_ieee1275_get_property (grub_ieee1275_chosen
,
186 bootp_response_properties
[i
].name
,
187 bootp_response
, size
, 0) < 0)
190 grub_net_configure_by_dhcp_ack (card
->name
, card
, 0,
191 (struct grub_net_bootp_packet
*)
193 + bootp_response_properties
[i
].offset
),
194 size
- bootp_response_properties
[i
].offset
,
196 grub_free (bootp_response
);
202 find_alias (const char *fullname
)
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
);
217 grub_devalias_iterate (find_alias_hook
);
218 grub_errno
= GRUB_ERR_NONE
;
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
;
231 if (grub_strcmp (alias
->type
, "network") != 0)
234 ofdata
= grub_malloc (sizeof (struct grub_ofnetcard_data
));
240 card
= grub_zalloc (sizeof (struct grub_net_card
));
248 ofdata
->path
= grub_strdup (alias
->path
);
250 grub_ieee1275_finddevice (ofdata
->path
, &devhandle
);
254 if (grub_ieee1275_get_integer_property (devhandle
,
255 "max-frame-size", &t
,
262 if (grub_ieee1275_get_property (devhandle
, "mac-address",
264 && grub_ieee1275_get_property (devhandle
, "local-mac-address",
267 grub_error (GRUB_ERR_IO
, "Couldn't retrieve mac address.");
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
))
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
;
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
296 grub_error (GRUB_ERR_OUT_OF_MEMORY
, N_("out of memory"));
299 card
->txbuf
= (void *) args
.result
;
302 card
->txbuf
= grub_zalloc (card
->txbufsize
);
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
);
322 grub_ofnet_findcards (void)
324 /* Look at all nodes for devices of the type network. */
325 grub_ieee1275_devices_iterate (search_net_devices
);
330 grub_ofnet_findcards ();
331 grub_ieee1275_net_config
= grub_ieee1275_net_config_real
;
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;