From: Vladimir 'phcoder' Serbinenko Date: Wed, 11 Apr 2012 20:32:31 +0000 (+0200) Subject: Terminate UNDI and PXE before launching the payload to avoid problems X-Git-Tag: 2.00~329 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3c491b479c549665292ea6e9323c48a194276c64;p=thirdparty%2Fgrub.git 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. --- diff --git a/ChangeLog b/ChangeLog index 76ddaf6d7..4f4913eb4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2012-04-11 Vladimir Serbinenko + + 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 * grub-core/normal/charset.c (grub_ucs4_to_utf8): Return number of diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c index b4bce3733..91ec87d80 100644 --- a/grub-core/commands/boot.c +++ b/grub-core/commands/boot.c @@ -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) diff --git a/grub-core/loader/i386/pc/pxechainloader.c b/grub-core/loader/i386/pc/pxechainloader.c index 4b528b6b8..e60c62b1b 100644 --- a/grub-core/loader/i386/pc/pxechainloader.c +++ b/grub-core/loader/i386/pc/pxechainloader.c @@ -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: diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 9895de472..27003f5ff 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -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); } diff --git a/include/grub/loader.h b/include/grub/loader.h index 432d8705d..7f82a499f 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -28,11 +28,16 @@ /* 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);