grub/grub-core/net/drivers/ieee1275/ofnet.c
Vladimir 'phcoder' Serbinenko 6b1b3423dd Fix error handling in ofnet
2010-09-22 17:14:14 +02:00

181 lines
4 KiB
C

#include <grub/net/netbuff.h>
#include <grub/ieee1275/ofnet.h>
#include <grub/ieee1275/ieee1275.h>
#include <grub/net.h>
static grub_err_t
card_open (struct grub_net_card *dev)
{
int status;
struct grub_ofnetcard_data *data = dev->data;
status = grub_ieee1275_open (data->path,&(data->handle));
if (status)
return grub_error (GRUB_ERR_IO, "couldn't open network card");
return GRUB_ERR_NONE;
}
static grub_err_t
card_close (struct grub_net_card *dev)
{
struct grub_ofnetcard_data *data = dev->data;
if (data->handle)
grub_ieee1275_close (data->handle);
return GRUB_ERR_NONE;
}
static grub_err_t
send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack)
{
int actual;
int status;
struct grub_ofnetcard_data *data = dev->data;
status = grub_ieee1275_write (data->handle, pack->data,
pack->tail - pack->data, &actual);
if (status)
return grub_error (GRUB_ERR_IO, "couldn't send network packet");
return GRUB_ERR_NONE;
}
static grub_err_t
get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack)
{
int actual, rc;
struct grub_ofnetcard_data *data = dev->data;
grub_netbuff_clear(pack);
do
rc = grub_ieee1275_read (data->handle, pack->data, 1500, &actual);
while (actual <= 0 || rc < 0);
grub_netbuff_put (pack, actual);
return GRUB_ERR_NONE;
}
static struct grub_net_card_driver ofdriver =
{
.name = "ofnet",
.init = card_open,
.fini = card_close,
.send = send_card_buffer,
.recv = get_card_packet
};
static const struct
{
char *name;
int offset;
}
bootp_response_properties[] =
{
{ .name = "bootp-response", .offset = 0 },
{ .name = "dhcp-response", .offset = 0 },
{ .name = "bootpreply-packet", .offset = 0x2a },
};
grub_bootp_t
grub_getbootp( void )
{
grub_bootp_t packet = grub_malloc(sizeof *packet);
void *bootp_response = NULL;
grub_ssize_t size;
unsigned int i;
for ( i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
bootp_response_properties[i].name,
&size) >= 0)
break;
if (size < 0)
{
grub_printf("Error to get bootp\n");
return NULL;
}
if (grub_ieee1275_get_property (grub_ieee1275_chosen,
bootp_response_properties[i].name,
bootp_response ,
size, 0) < 0)
{
grub_printf("Error to get bootp\n");
return NULL;
}
packet = (void *) ((int)bootp_response
+ bootp_response_properties[i].offset);
return packet;
}
void grub_ofnet_findcards (void)
{
struct grub_net_card *card;
int i = 0;
auto int search_net_devices (struct grub_ieee1275_devalias *alias);
int search_net_devices (struct grub_ieee1275_devalias *alias)
{
if ( !grub_strcmp (alias->type,"network") )
{
card = grub_malloc (sizeof (struct grub_net_card));
struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data));
ofdata->path = grub_strdup (alias->path);
card->data = ofdata;
card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name);
grub_net_card_register (card);
}
return 0;
}
/*Look at all nodes for devices of the type network*/
grub_ieee1275_devices_iterate (search_net_devices);
}
void grub_ofnet_probecards (void)
{
struct grub_net_card *card;
struct grub_net_card_driver *driver;
/*Assign correspondent driver for each device. */
FOR_NET_CARDS (card)
{
FOR_NET_CARD_DRIVERS (driver)
{
if (driver->init(card) == GRUB_ERR_NONE)
{
card->driver = driver;
continue;
}
}
}
}
GRUB_MOD_INIT(ofnet)
{
grub_net_card_driver_register (&ofdriver);
grub_ofnet_findcards();
grub_ofnet_probecards();
/*init tftp stack - will be handled by module subsystem in the future*/
tftp_ini ();
/*get bootp packet - won't be needed in the future*/
bootp_pckt = grub_getbootp ();
grub_disknet_init();
}
GRUB_MODE_FINI(ofnet)
{
grub_net_card_driver_unregister (&ofdriver);
}