On module unload each of its network cards are unregistered,
but corresponding memory areas are not freed.

This commit is to fix this situation.

Freeing the transmit buffer goes via a special function, since
it is allocated via ofnet_alloc_netbuf().

Signed-off-by: Stanislav Kholmanskikh <[email protected]>
---
 grub-core/net/drivers/ieee1275/ofnet.c |   61 +++++++++++++++++++++++++++++++-
 1 files changed, 60 insertions(+), 1 deletions(-)

diff --git a/grub-core/net/drivers/ieee1275/ofnet.c 
b/grub-core/net/drivers/ieee1275/ofnet.c
index 25559c8..1f8ac9a 100644
--- a/grub-core/net/drivers/ieee1275/ofnet.c
+++ b/grub-core/net/drivers/ieee1275/ofnet.c
@@ -331,6 +331,40 @@ grub_ieee1275_alloc_mem (grub_size_t len)
     return (void *)args.result;
 }
 
+/* Free memory allocated by alloc-mem */
+static grub_err_t
+grub_ieee1275_free_mem (void *addr, grub_size_t len)
+{
+  struct free_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t len;
+    grub_ieee1275_cell_t addr;
+    grub_ieee1275_cell_t catch;
+  }
+  args;
+
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("interpret is not supported"));
+      return grub_errno;
+    }
+
+  INIT_IEEE1275_COMMON (&args.common, "interpret", 3, 1);
+  args.addr = (grub_ieee1275_cell_t)addr;
+  args.len = len;
+  args.method = (grub_ieee1275_cell_t) "free-mem";
+
+  if (IEEE1275_CALL_ENTRY_FN(&args) == -1 || args.catch)
+    {
+      grub_error (GRUB_ERR_INVALID_COMMAND, N_("free-mem failed"));
+      return grub_errno;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
 static void *
 ofnet_alloc_netbuf (grub_size_t len)
 {
@@ -340,6 +374,15 @@ ofnet_alloc_netbuf (grub_size_t len)
     return grub_zalloc (len);
 }
 
+static void
+ofnet_free_netbuf (void *addr, grub_size_t len)
+{
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
+    grub_ieee1275_free_mem (addr, len);
+  else
+    grub_free (addr);
+}
+
 static int
 search_net_devices (struct grub_ieee1275_devalias *alias)
 {
@@ -494,9 +537,25 @@ GRUB_MOD_INIT(ofnet)
 GRUB_MOD_FINI(ofnet)
 {
   struct grub_net_card *card, *next;
+  struct grub_ofnetcard_data *ofdata;
 
   FOR_NET_CARDS_SAFE (card, next) 
     if (card->driver && grub_strcmp (card->driver->name, "ofnet") == 0)
-      grub_net_card_unregister (card);
+      {
+       grub_net_card_unregister (card);
+       /*
+        * The fact that we are here means the card was successfully
+        * initialized in the past, so all the below pointers are valid,
+        * and we may free associated memory without checks.
+        */
+       ofdata = (struct grub_ofnetcard_data *) card->data;
+       grub_free (ofdata->path);
+       grub_free (ofdata);
+
+       ofnet_free_netbuf (card->txbuf, card->txbufsize);
+
+       grub_free ((void *) card->name);
+       grub_free (card);
+      }
   grub_ieee1275_net_config = 0;
 }
-- 
1.7.1


_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to