*/
 #define MAX_ADDR_LEN 19
 
-static acpi_physical_address get_acpi_rsdp(void)
+static acpi_physical_address get_cmdline_acpi_rsdp(void)
 {
        acpi_physical_address addr = 0;
 
 {
        acpi_physical_address pa;
 
-       pa = get_acpi_rsdp();
-
-       if (!pa)
-               pa = boot_params->acpi_rsdp_addr;
+       pa = boot_params->acpi_rsdp_addr;
 
        if (!pa)
                pa = efi_get_rsdp_addr();
        char arg[10];
        u8 *entry;
 
-       rsdp = (struct acpi_table_rsdp *)(long)boot_params->acpi_rsdp_addr;
+       /*
+        * Check whether we were given an RSDP on the command line. We don't
+        * stash this in boot params because the kernel itself may have
+        * different ideas about whether to trust a command-line parameter.
+        */
+       rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
+
+       if (!rsdp)
+               rsdp = (struct acpi_table_rsdp *)(long)
+                       boot_params->acpi_rsdp_addr;
+
        if (!rsdp)
                return 0;
 
 
        return !!acpi_lapic;
 }
 
+#define ACPI_HAVE_ARCH_SET_ROOT_POINTER
+static inline void acpi_arch_set_root_pointer(u64 addr)
+{
+       x86_init.acpi.set_root_pointer(addr);
+}
+
 #define ACPI_HAVE_ARCH_GET_ROOT_POINTER
 static inline u64 acpi_arch_get_root_pointer(void)
 {
 
 void acpi_generic_reduced_hw_init(void);
 
+void x86_default_set_root_pointer(u64 addr);
 u64 x86_default_get_root_pointer(void);
 
 #else /* !CONFIG_ACPI */
 
 static inline void acpi_generic_reduced_hw_init(void) { }
 
+static inline void x86_default_set_root_pointer(u64 addr) { }
+
 static inline u64 x86_default_get_root_pointer(void)
 {
        return 0;
 
 
 /**
  * struct x86_init_acpi - x86 ACPI init functions
+ * @set_root_poitner:          set RSDP address
  * @get_root_pointer:          get RSDP address
  * @reduced_hw_early_init:     hardware reduced platform early init
  */
 struct x86_init_acpi {
+       void (*set_root_pointer)(u64 addr);
        u64 (*get_root_pointer)(void);
        void (*reduced_hw_early_init)(void);
 };
 
        e820__update_table_print();
 }
 
+void x86_default_set_root_pointer(u64 addr)
+{
+       boot_params.acpi_rsdp_addr = addr;
+}
+
 u64 x86_default_get_root_pointer(void)
 {
        return boot_params.acpi_rsdp_addr;
 
        },
 
        .acpi = {
+               .set_root_pointer       = x86_default_set_root_pointer,
                .get_root_pointer       = x86_default_get_root_pointer,
                .reduced_hw_early_init  = acpi_generic_reduced_hw_init,
        },
 
 #include <linux/list.h>
 #include <linux/jiffies.h>
 #include <linux/semaphore.h>
+#include <linux/security.h>
 
 #include <asm/io.h>
 #include <linux/uaccess.h>
        acpi_physical_address pa;
 
 #ifdef CONFIG_KEXEC
-       if (acpi_rsdp)
+       /*
+        * We may have been provided with an RSDP on the command line,
+        * but if a malicious user has done so they may be pointing us
+        * at modified ACPI tables that could alter kernel behaviour -
+        * so, we check the lockdown status before making use of
+        * it. If we trust it then also stash it in an architecture
+        * specific location (if appropriate) so it can be carried
+        * over further kexec()s.
+        */
+       if (acpi_rsdp && !security_locked_down(LOCKDOWN_ACPI_TABLES)) {
+               acpi_arch_set_root_pointer(acpi_rsdp);
                return acpi_rsdp;
+       }
 #endif
        pa = acpi_arch_get_root_pointer();
        if (pa)
 
 int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count);
 #endif
 
+#ifndef ACPI_HAVE_ARCH_SET_ROOT_POINTER
+static inline void acpi_arch_set_root_pointer(u64 addr)
+{
+}
+#endif
+
 #ifndef ACPI_HAVE_ARCH_GET_ROOT_POINTER
 static inline u64 acpi_arch_get_root_pointer(void)
 {