]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Terminate UNDI and PXE before launching the payload to avoid problems
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 11 Apr 2012 20:32:31 +0000 (22:32 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 11 Apr 2012 20:32:31 +0000 (22:32 +0200)
with DMA.

* grub-core/commands/boot.c (grub_loader_noreturn): Rename to ...
(grub_loader_flags): ... this. All users updated.
(grub_loader_boot): Check for GRUB_LOADER_FLAG_NORETURN.
* grub-core/loader/i386/pc/pxechainloader.c (grub_cmd_pxechain): Mark
loader as GRUB_LOADER_FLAG_PXE_NOT_UNLOAD.
* grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_shutdown): New
function.
(grub_pxe_restore): Likewise.
(fini_hnd): New var.
(GRUB_MOD_INIT): Register shutdown hook.
(GRUB_MOD_FINI): Shutdown and unregister shutdown hook.
* include/grub/loader.h (GRUB_LOADER_FLAG_NORETURN): New const.
(GRUB_LOADER_FLAG_PXE_NOT_UNLOAD): Likewise.
(grub_loader_set): Rename second argument to flags.

ChangeLog
grub-core/commands/boot.c
grub-core/loader/i386/pc/pxechainloader.c
grub-core/net/drivers/i386/pc/pxe.c
include/grub/loader.h

index 76ddaf6d77b2db902caedaa9d96ca35b6b93bbe4..4f4913eb4b6d1c43559d45c19ed04ce5490a947a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2012-04-11  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Terminate UNDI and PXE before launching the payload to avoid problems
+       with DMA.
+
+       * grub-core/commands/boot.c (grub_loader_noreturn): Rename to ...
+       (grub_loader_flags): ... this. All users updated.
+       (grub_loader_boot): Check for GRUB_LOADER_FLAG_NORETURN.
+       * grub-core/loader/i386/pc/pxechainloader.c (grub_cmd_pxechain): Mark
+       loader as GRUB_LOADER_FLAG_PXE_NOT_UNLOAD.
+       * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_shutdown): New
+       function.
+       (grub_pxe_restore): Likewise.
+       (fini_hnd): New var.
+       (GRUB_MOD_INIT): Register shutdown hook.
+       (GRUB_MOD_FINI): Shutdown and unregister shutdown hook.
+       * include/grub/loader.h (GRUB_LOADER_FLAG_NORETURN): New const.
+       (GRUB_LOADER_FLAG_PXE_NOT_UNLOAD): Likewise.
+       (grub_loader_set): Rename second argument to flags.
+
 2012-04-07  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/normal/charset.c (grub_ucs4_to_utf8): Return number of
index b4bce37337cbb3be8e46608cdb108fd3f6f298d6..91ec87d809492c90a53dc6c3fe8667e394004164 100644 (file)
@@ -29,7 +29,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 static grub_err_t (*grub_loader_boot_func) (void);
 static grub_err_t (*grub_loader_unload_func) (void);
-static int grub_loader_noreturn;
+static int grub_loader_flags;
 
 struct grub_preboot
 {
@@ -52,7 +52,7 @@ grub_loader_is_loaded (void)
 
 /* Register a preboot hook. */
 struct grub_preboot *
-grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
+grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int flags),
                                   grub_err_t (*preboot_rest_func) (void),
                                   grub_loader_preboot_hook_prio_t prio)
 {
@@ -112,14 +112,14 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
 void
 grub_loader_set (grub_err_t (*boot) (void),
                 grub_err_t (*unload) (void),
-                int noreturn)
+                int flags)
 {
   if (grub_loader_loaded && grub_loader_unload_func)
     grub_loader_unload_func ();
 
   grub_loader_boot_func = boot;
   grub_loader_unload_func = unload;
-  grub_loader_noreturn = noreturn;
+  grub_loader_flags = flags;
 
   grub_loader_loaded = 1;
 }
@@ -146,12 +146,12 @@ grub_loader_boot (void)
     return grub_error (GRUB_ERR_NO_KERNEL,
                       N_("you need to load the kernel first"));
 
-  if (grub_loader_noreturn)
+  if (grub_loader_flags & GRUB_LOADER_FLAG_NORETURN)
     grub_machine_fini ();
 
   for (cur = preboots_head; cur; cur = cur->next)
     {
-      err = cur->preboot_func (grub_loader_noreturn);
+      err = cur->preboot_func (grub_loader_flags);
       if (err)
        {
          for (cur = cur->prev; cur; cur = cur->prev)
index 4b528b6b826a75b5a1f469b19c31d509bafa95c0..e60c62b1badd958ade575040384e10dff90f95dd 100644 (file)
@@ -139,7 +139,8 @@ grub_cmd_pxechain (grub_command_t cmd __attribute__ ((unused)),
   if (grub_file_read (file, image, imagesize) != (grub_ssize_t) imagesize)
     goto fail;
  
-  grub_loader_set (grub_pxechain_boot, grub_pxechain_unload, 1);
+  grub_loader_set (grub_pxechain_boot, grub_pxechain_unload,
+                  GRUB_LOADER_FLAG_NORETURN | GRUB_LOADER_FLAG_PXE_NOT_UNLOAD);
   return GRUB_ERR_NONE;
 
  fail:
index 9895de4720f9c98f993c255810da8aa465d1383c..27003f5ff121e80c6626413b45a812443771c342 100644 (file)
@@ -24,6 +24,7 @@
 #include <grub/misc.h>
 #include <grub/env.h>
 #include <grub/i18n.h>
+#include <grub/loader.h>
 
 #include <grub/machine/pxe.h>
 #include <grub/machine/int.h>
@@ -311,6 +312,36 @@ struct grub_net_card grub_pxe_card =
   .name = "pxe"
 };
 
+static grub_err_t
+grub_pxe_shutdown (int flags)
+{
+  if (flags & GRUB_LOADER_FLAG_PXE_NOT_UNLOAD)
+    return GRUB_ERR_NONE;
+  if (!pxe_rm_entry)
+    return GRUB_ERR_NONE;
+
+  grub_pxe_call (GRUB_PXENV_UNDI_CLOSE,
+                (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+                pxe_rm_entry);
+  grub_pxe_call (GRUB_PXENV_UNDI_SHUTDOWN,
+                (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+                pxe_rm_entry);
+  grub_pxe_call (GRUB_PXENV_UNLOAD_STACK,
+                (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+                pxe_rm_entry);
+  pxe_rm_entry = 0;
+  grub_net_card_unregister (&grub_pxe_card);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Nothing we can do.  */
+static grub_err_t
+grub_pxe_restore (void)
+{
+  return GRUB_ERR_NONE;
+}
+
 void *
 grub_pxe_get_cached (grub_uint16_t type)
 {
@@ -340,6 +371,8 @@ grub_pc_net_config_real (char **device, char **path)
 
 }
 
+static struct grub_preboot *fini_hnd;
+
 GRUB_MOD_INIT(pxe)
 {
   struct grub_pxe_bangpxe *pxenv;
@@ -374,10 +407,14 @@ GRUB_MOD_INIT(pxe)
 
   grub_net_card_register (&grub_pxe_card);
   grub_pc_net_config = grub_pc_net_config_real;
+  fini_hnd = grub_loader_register_preboot_hook (grub_pxe_shutdown,
+                                               grub_pxe_restore,
+                                               GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
 }
 
 GRUB_MOD_FINI(pxe)
 {
   grub_pc_net_config = 0;
-  grub_net_card_unregister (&grub_pxe_card);
+  grub_pxe_shutdown (0);
+  grub_loader_unregister_preboot_hook (fini_hnd);
 }
index 432d8705d65da97dca86cdde2ad5a9960cf15b51..7f82a499fd9c025643b7f757ecb489bbac2a285c 100644 (file)
 /* Check if a loader is loaded.  */
 int EXPORT_FUNC (grub_loader_is_loaded) (void);
 
-/* Set loader functions. NORETURN must be set to true, if BOOT won't return
-   to the original state.  */
+/* Set loader functions.  */
+enum
+{
+  GRUB_LOADER_FLAG_NORETURN = 1,
+  GRUB_LOADER_FLAG_PXE_NOT_UNLOAD = 2,
+};
+
 void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
-                                        grub_err_t (*unload) (void),
-                                        int noreturn);
+                                   grub_err_t (*unload) (void),
+                                   int flags);
 
 /* Unset current loader, if any.  */
 void EXPORT_FUNC (grub_loader_unset) (void);