From 0494408e7ec400c75b298c72736c5ec1e3f53ba3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 19 Jun 2012 11:34:52 +0200 Subject: [PATCH] * include/grub/net.h (grub_net_card): New member txbufsize. * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New enum values GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX and GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN. * grub-core/net/drivers/efi/efinet.c (grub_efinet_findcards): Use txbufsize. * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Use compatible property to check for macs. Set GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX and GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN on macs. * grub-core/net/drivers/ieee1275/ofnet.c (card_open): Don't add suffix if GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX is set. (send_card_buffer): Use txbuf. (grub_ofnet_findcards): Allocate txbuf. Simplify code flow and move nested function out of the parent while on it. --- ChangeLog | 18 +++ grub-core/kern/ieee1275/cmain.c | 24 ++- grub-core/net/drivers/efi/efinet.c | 3 +- grub-core/net/drivers/ieee1275/ofnet.c | 193 +++++++++++++++---------- include/grub/ieee1275/ieee1275.h | 6 +- include/grub/net.h | 1 + 6 files changed, 164 insertions(+), 81 deletions(-) diff --git a/ChangeLog b/ChangeLog index b401bda35..13ef6b06b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2012-06-19 Vladimir Serbinenko + + * include/grub/net.h (grub_net_card): New member txbufsize. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New enum values + GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX and + GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN. + * grub-core/net/drivers/efi/efinet.c (grub_efinet_findcards): Use + txbufsize. + * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Use + compatible property to check for macs. Set + GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX and + GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN on macs. + * grub-core/net/drivers/ieee1275/ofnet.c (card_open): Don't add suffix + if GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX is set. + (send_card_buffer): Use txbuf. + (grub_ofnet_findcards): Allocate txbuf. Simplify code flow and move + nested function out of the parent while on it. + 2012-06-19 Vladimir Serbinenko * grub-core/net/drivers/ieee1275/ofnet.c (get_card_packet): Fix packet diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index 965ad05ce..763f83394 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -55,10 +55,11 @@ grub_ieee1275_find_options (void) grub_ieee1275_phandle_t bootrom; int rc; grub_uint32_t realmode = 0; - char tmp[32]; + char tmp[256]; int is_smartfirmware = 0; int is_olpc = 0; int is_qemu = 0; + grub_ssize_t actual; #ifdef __sparc__ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0); @@ -91,9 +92,24 @@ grub_ieee1275_find_options (void) if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0) grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS); - if (grub_strncmp (tmp, "PowerMac", sizeof ("PowerMac") - 1) == 0 - || grub_strncmp (tmp, "RackMac", sizeof ("RackMac") - 1) == 0) - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS); + rc = grub_ieee1275_get_property (root, "compatible", + tmp, sizeof (tmp), &actual); + if (rc >= 0) + { + char *ptr; + for (ptr = tmp; ptr - tmp < actual; ptr += grub_strlen (ptr) + 1) + { + if (grub_memcmp (ptr, "MacRISC", sizeof ("MacRISC") - 1) == 0 + && (ptr[sizeof ("MacRISC") - 1] == 0 + || grub_isdigit (ptr[sizeof ("MacRISC") - 1]))) + { + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN); + break; + } + } + } if (is_smartfirmware) { diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index e42eae745..28f2db27f 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -181,7 +181,8 @@ grub_efinet_findcards (void) } card->mtu = net->mode->max_packet_size; - card->txbuf = grub_zalloc (ALIGN_UP (card->mtu, 64) + 256); + card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; + card->txbuf = grub_zalloc (card->txbufsize); if (!card->txbuf) { grub_print_error (); diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index a31b77fe0..61b6a69a7 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -36,13 +36,19 @@ card_open (struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; - char path[grub_strlen (data->path) + - grub_strlen (":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; - /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */ - grub_snprintf (path, sizeof (path), "%s%s", data->path, - ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); - status = grub_ieee1275_open (path, &(data->handle)); + if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX)) + { + char path[grub_strlen (data->path) + + 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")]; + + /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */ + grub_snprintf (path, sizeof (path), "%s%s", data->path, + ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); + status = grub_ieee1275_open (path, &(data->handle)); + } + else + status = grub_ieee1275_open (data->path, &(data->handle)); if (status) return grub_error (GRUB_ERR_IO, "Couldn't open network card."); @@ -65,8 +71,14 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) grub_ssize_t actual; int status; struct grub_ofnetcard_data *data = dev->data; + grub_size_t len; - status = grub_ieee1275_write (data->handle, pack->data, + len = (pack->tail - pack->data); + if (len > dev->mtu) + len = dev->mtu; + + grub_memcpy (dev->txbuf, pack->data, len); + status = grub_ieee1275_write (data->handle, dev->txbuf, pack->tail - pack->data, &actual); if (status) @@ -205,77 +217,108 @@ find_alias (const char *fullname) return ret; } +static int +search_net_devices (struct grub_ieee1275_devalias *alias) +{ + struct grub_ofnetcard_data *ofdata; + struct grub_net_card *card; + grub_ieee1275_phandle_t devhandle; + grub_net_link_level_address_t lla; + char *shortname; + + if (grub_strcmp (alias->type, "network") != 0) + return 0; + + ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); + if (!ofdata) + { + grub_print_error (); + return 1; + } + card = grub_zalloc (sizeof (struct grub_net_card)); + if (!card) + { + grub_free (ofdata); + grub_print_error (); + return 1; + } + + ofdata->path = grub_strdup (alias->path); + + grub_ieee1275_finddevice (ofdata->path, &devhandle); + + { + grub_uint32_t t; + if (grub_ieee1275_get_integer_property (devhandle, + "max-frame-size", &t, + sizeof (t), 0)) + card->mtu = 1500; + else + card->mtu = t; + } + + if (grub_ieee1275_get_property (devhandle, "mac-address", + &(lla.mac), 6, 0) + && grub_ieee1275_get_property (devhandle, "local-mac-address", + &(lla.mac), 6, 0)) + { + grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + grub_print_error (); + return 0; + } + + lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + card->default_address = lla; + + card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN)) + { + struct alloc_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t len; + grub_ieee1275_cell_t catch; + grub_ieee1275_cell_t result; + } + args; + INIT_IEEE1275_COMMON (&args.common, "interpret", 2, 2); + args.len = card->txbufsize; + args.method = (grub_ieee1275_cell_t) "alloc-mem"; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1 + || args.catch) + { + card->txbuf = 0; + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + } + else + card->txbuf = (void *) args.result; + } + else + card->txbuf = grub_zalloc (card->txbufsize); + if (!card->txbuf) + { + grub_print_error (); + return 0; + } + card->driver = NULL; + card->data = ofdata; + card->flags = 0; + shortname = find_alias (alias->path); + card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path); + card->idle_poll_delay_ms = 1; + grub_free (shortname); + + card->driver = &ofdriver; + grub_net_card_register (card); + return 0; +} + static void grub_ofnet_findcards (void) { - 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")) - { - struct grub_ofnetcard_data *ofdata; - struct grub_net_card *card; - grub_ieee1275_phandle_t devhandle; - grub_net_link_level_address_t lla; - char *shortname; - - ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); - if (!ofdata) - { - grub_print_error (); - return 1; - } - card = grub_zalloc (sizeof (struct grub_net_card)); - if (!card) - { - grub_free (ofdata); - grub_print_error (); - return 1; - } - - ofdata->path = grub_strdup (alias->path); - - grub_ieee1275_finddevice (ofdata->path, &devhandle); - - { - grub_uint32_t t; - if (grub_ieee1275_get_integer_property (devhandle, - "max-frame-size", &t, - sizeof (t), 0)) - card->mtu = 1500; - else - card->mtu = t; - } - - if (grub_ieee1275_get_property (devhandle, "mac-address", - &(lla.mac), 6, 0) - && grub_ieee1275_get_property (devhandle, "local-mac-address", - &(lla.mac), 6, 0)) - { - grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); - grub_print_error (); - return 0; - } - - lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - card->default_address = lla; - - card->driver = NULL; - card->data = ofdata; - card->flags = 0; - shortname = find_alias (alias->path); - card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path); - card->idle_poll_delay_ms = 1; - grub_free (shortname); - - card->driver = &ofdriver; - grub_net_card_register (card); - return 0; - } - return 0; - } - /* Look at all nodes for devices of the type network. */ grub_ieee1275_devices_iterate (search_net_devices); } diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 99a4bc172..451ea44ae 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -117,7 +117,11 @@ enum grub_ieee1275_flag */ GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS, - GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS + GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS, + + GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX, + + GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN }; extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); diff --git a/include/grub/net.h b/include/grub/net.h index d854ed2de..859f81f15 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -129,6 +129,7 @@ struct grub_net_card void *txbuf; void *rcvbuf; grub_size_t rcvbufsize; + grub_size_t txbufsize; int txbusy; union {