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-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
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
{
/* 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)
{
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;
}
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)
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:
#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>
.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)
{
}
+static struct grub_preboot *fini_hnd;
+
GRUB_MOD_INIT(pxe)
{
struct grub_pxe_bangpxe *pxenv;
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);
}
/* 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);