summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kexec/arch/i386/crashdump-x86.h9
-rw-r--r--kexec/arch/i386/kexec-bzImage.c2
-rw-r--r--kexec/arch/i386/kexec-elf-x86.c19
-rw-r--r--kexec/arch/i386/kexec-multiboot-x86.c3
-rw-r--r--kexec/arch/i386/kexec-x86.c32
-rw-r--r--kexec/arch/i386/x86-linux-setup.c5
-rw-r--r--kexec/arch/i386/x86-linux-setup.h3
-rw-r--r--kexec/arch/ia64/kexec-ia64.c11
-rw-r--r--kexec/arch/ppc/kexec-ppc.c7
-rw-r--r--kexec/arch/x86_64/kexec-x86_64.c7
-rw-r--r--kexec/kexec.c17
-rw-r--r--kexec/kexec.h9
-rw-r--r--purgatory/arch/i386/Makefile1
-rw-r--r--purgatory/arch/i386/crashdump_backup.c44
-rw-r--r--purgatory/arch/i386/purgatory-x86.c7
-rw-r--r--purgatory/arch/i386/purgatory-x86.h1
-rw-r--r--purgatory/arch/ia64/purgatory-ia64.c6
-rw-r--r--purgatory/arch/ppc/purgatory-ppc.c6
-rw-r--r--purgatory/arch/x86_64/purgatory-x86_64.c6
-rw-r--r--purgatory/include/purgatory.h1
-rw-r--r--purgatory/purgatory.c1
21 files changed, 167 insertions, 30 deletions
diff --git a/kexec/arch/i386/crashdump-x86.h b/kexec/arch/i386/crashdump-x86.h
new file mode 100644
index 0000000..d26a5dd
--- /dev/null
+++ b/kexec/arch/i386/crashdump-x86.h
@@ -0,0 +1,9 @@
+#ifndef CRASHDUMP_X86_H
+#define CRASHDUMP_X86_H
+
+/* Backup Region, First 640K of System RAM. */
+#define BACKUP_START 0x00000000
+#define BACKUP_END 0x0009ffff
+#define BACKUP_SIZE (BACKUP_END - BACKUP_START + 1)
+
+#endif /* CRASHDUMP_X86_H */
diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c
index 9de2dc8..9450346 100644
--- a/kexec/arch/i386/kexec-bzImage.c
+++ b/kexec/arch/i386/kexec-bzImage.c
@@ -214,7 +214,7 @@ int do_bzImage_load(struct kexec_info *info,
/* Fill in the information BIOS calls would normally provide. */
if (!real_mode_entry) {
- setup_linux_system_parameters(real_mode);
+ setup_linux_system_parameters(real_mode, info->kexec_flags);
}
return 0;
diff --git a/kexec/arch/i386/kexec-elf-x86.c b/kexec/arch/i386/kexec-elf-x86.c
index 7d1e7f9..808fa75 100644
--- a/kexec/arch/i386/kexec-elf-x86.c
+++ b/kexec/arch/i386/kexec-elf-x86.c
@@ -32,10 +32,12 @@
#include <elf.h>
#include <x86/x86-linux.h>
#include "../../kexec.h"
+#include "../../kexec-syscall.h"
#include "../../kexec-elf.h"
#include "../../kexec-elf-boot.h"
#include "x86-linux-setup.h"
#include "kexec-x86.h"
+#include "crashdump-x86.h"
#include <arch/options.h>
static const int probe_debug = 0;
@@ -220,6 +222,21 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
}
+ /* If panic kernel is being loaded, additional segments need
+ * to be created. */
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ void *tmp;
+ unsigned long sz;
+ int nr_ranges, align = 1024;
+ /* Create a backup region segment to store first 640K
+ * memory*/
+ sz = (BACKUP_SIZE + align - 1) & ~(align - 1);
+ tmp = xmalloc(sz);
+ memset(tmp, 0, sz);
+ info->backup_start = add_buffer(info, tmp, sz, sz, 1024,
+ 0, max_addr, 1);
+ }
+
/* Tell the kernel what is going on */
setup_linux_bootloader_parameters(info, &hdr->hdr, param_base,
offsetof(struct x86_linux_faked_param_header, command_line),
@@ -227,7 +244,7 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
ramdisk_buf, ramdisk_length);
/* Fill in the information bios calls would usually provide */
- setup_linux_system_parameters(&hdr->hdr);
+ setup_linux_system_parameters(&hdr->hdr, info->kexec_flags);
/* Initialize the registers */
elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
diff --git a/kexec/arch/i386/kexec-multiboot-x86.c b/kexec/arch/i386/kexec-multiboot-x86.c
index 0efefc9..9414bfe 100644
--- a/kexec/arch/i386/kexec-multiboot-x86.c
+++ b/kexec/arch/i386/kexec-multiboot-x86.c
@@ -246,7 +246,8 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
mbi->boot_loader_name = sizeof(*mbi) + command_line_len;
/* Memory map */
- if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
+ if ((get_memory_ranges(&range, &ranges, info->kexec_flags) < 0)
+ || ranges == 0) {
fprintf(stderr, "Cannot get memory information\n");
return -1;
}
diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
index 1159686..41a0985 100644
--- a/kexec/arch/i386/kexec-x86.c
+++ b/kexec/arch/i386/kexec-x86.c
@@ -37,7 +37,8 @@
static struct memory_range memory_range[MAX_MEMORY_RANGES];
/* Return a sorted list of memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags)
{
const char iomem[]= "/proc/iomem";
int memory_ranges = 0;
@@ -79,6 +80,20 @@ int get_memory_ranges(struct memory_range **range, int *ranges)
else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
type = RANGE_ACPI_NVS;
}
+ else if (memcmp(str, "Crash kernel\n", 13) == 0) {
+ /* Redefine the memory region boundaries if kernel
+ * exports the limits and if it is panic kernel.
+ * Override user values only if kernel exported values are
+ * subset of user defined values.
+ */
+ if (kexec_flags & KEXEC_ON_CRASH) {
+ if (start > mem_min)
+ mem_min = start;
+ if (end < mem_max)
+ mem_max = end;
+ }
+ continue;
+ }
else {
continue;
}
@@ -206,7 +221,7 @@ int arch_process_options(int argc, char **argv)
return 0;
}
-int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+int arch_compat_trampoline(struct kexec_info *info)
{
int result;
struct utsname utsname;
@@ -224,11 +239,11 @@ int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
/* For compatibility with older patches
* use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_386 here.
*/
- *flags |= KEXEC_ARCH_DEFAULT;
+ info->kexec_flags |= KEXEC_ARCH_DEFAULT;
}
else if (strcmp(utsname.machine, "x86_64") == 0)
{
- *flags |= KEXEC_ARCH_X86_64;
+ info->kexec_flags |= KEXEC_ARCH_X86_64;
if (!info->rhdr.e_shdr) {
fprintf(stderr,
"A trampoline is required for cross architecture support\n");
@@ -249,6 +264,8 @@ int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
void arch_update_purgatory(struct kexec_info *info)
{
+ uint8_t panic_kernel = 0;
+
elf_rel_set_symbol(&info->rhdr, "reset_vga",
&arch_options.reset_vga, sizeof(arch_options.reset_vga));
elf_rel_set_symbol(&info->rhdr, "serial_base",
@@ -259,4 +276,11 @@ void arch_update_purgatory(struct kexec_info *info)
&arch_options.console_vga, sizeof(arch_options.console_vga));
elf_rel_set_symbol(&info->rhdr, "console_serial",
&arch_options.console_serial, sizeof(arch_options.console_serial));
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ panic_kernel = 1;
+ elf_rel_set_symbol(&info->rhdr, "backup_start",
+ &info->backup_start, sizeof(info->backup_start));
+ }
+ elf_rel_set_symbol(&info->rhdr, "panic_kernel",
+ &panic_kernel, sizeof(panic_kernel));
}
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index 3ab4c7f..14acf8e 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -94,7 +94,8 @@ void setup_linux_bootloader_parameters(
cmdline_ptr[cmdline_len - 1] = '\0';
}
-void setup_linux_system_parameters(struct x86_linux_param_header *real_mode)
+void setup_linux_system_parameters(struct x86_linux_param_header *real_mode,
+ unsigned long kexec_flags)
{
/* Fill in information the BIOS would usually provide */
struct memory_range *range;
@@ -135,7 +136,7 @@ void setup_linux_system_parameters(struct x86_linux_param_header *real_mode)
real_mode->aux_device_info = 0;
/* Fill in the memory info */
- if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
+ if ((get_memory_ranges(&range, &ranges, kexec_flags) < 0) || ranges == 0) {
die("Cannot get memory information\n");
}
if (ranges > E820MAX) {
diff --git a/kexec/arch/i386/x86-linux-setup.h b/kexec/arch/i386/x86-linux-setup.h
index 79e65f3..13784cf 100644
--- a/kexec/arch/i386/x86-linux-setup.h
+++ b/kexec/arch/i386/x86-linux-setup.h
@@ -7,7 +7,8 @@ void setup_linux_bootloader_parameters(
unsigned long real_mode_base, unsigned long cmdline_offset,
const char *cmdline, off_t cmdline_len,
const unsigned char *initrd_buf, off_t initrd_size);
-void setup_linux_system_parameters(struct x86_linux_param_header *real_mode);
+void setup_linux_system_parameters(struct x86_linux_param_header *real_mode,
+ unsigned long kexec_flags);
#define SETUP_BASE 0x90000
diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c
index b876318..a2221e6 100644
--- a/kexec/arch/ia64/kexec-ia64.c
+++ b/kexec/arch/ia64/kexec-ia64.c
@@ -38,7 +38,8 @@
static struct memory_range memory_range[MAX_MEMORY_RANGES];
/* Return a sorted list of available memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags)
{
int memory_ranges;
/*
@@ -103,7 +104,7 @@ int arch_process_options(int argc, char **argv)
return 0;
}
-int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+int arch_compat_trampoline(struct kexec_info *info)
{
int result;
struct utsname utsname;
@@ -115,7 +116,7 @@ int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
}
if (strcmp(utsname.machine, "ia64") == 0)
{
- *flags |= KEXEC_ARCH_X86_64;
+ info->kexec_flags |= KEXEC_ARCH_X86_64;
}
else {
fprintf(stderr, "Unsupported machine type: %s\n",
@@ -125,7 +126,7 @@ int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
return 0;
}
-int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+int arch_compat_trampoline(struct kexec_info *info)
{
int result;
struct utsname utsname;
@@ -140,7 +141,7 @@ int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
/* For compatibility with older patches
* use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_IA64 here.
*/
- *flags |= KEXEC_ARCH_DEFAULT;
+ info->kexec_flags |= KEXEC_ARCH_DEFAULT;
}
else {
fprintf(stderr, "Unsupported machine type: %s\n",
diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
index 72c5b95..455febf 100644
--- a/kexec/arch/ppc/kexec-ppc.c
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -23,7 +23,8 @@
static struct memory_range memory_range[MAX_MEMORY_RANGES];
/* Return a sorted list of memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags)
{
int memory_ranges = 0;
#ifdef CONFIG_GAMECUBE
@@ -120,7 +121,7 @@ int arch_process_options(int argc, char **argv)
return 0;
}
-int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+int arch_compat_trampoline(struct kexec_info *info)
{
int result;
struct utsname utsname;
@@ -135,7 +136,7 @@ int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
/* For compatibility with older patches
* use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_PPC here.
*/
- *flags |= KEXEC_ARCH_DEFAULT;
+ info->kexec_flags |= KEXEC_ARCH_DEFAULT;
}
else {
fprintf(stderr, "Unsupported machine type: %s\n",
diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
index 523b2b0..557a478 100644
--- a/kexec/arch/x86_64/kexec-x86_64.c
+++ b/kexec/arch/x86_64/kexec-x86_64.c
@@ -37,7 +37,8 @@
static struct memory_range memory_range[MAX_MEMORY_RANGES];
/* Return a sorted list of memory ranges. */
-int get_memory_ranges(struct memory_range **range, int *ranges)
+int get_memory_ranges(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags)
{
const char iomem[]= "/proc/iomem";
int memory_ranges = 0;
@@ -207,7 +208,7 @@ int arch_process_options(int argc, char **argv)
return 0;
}
-int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+int arch_compat_trampoline(struct kexec_info *info)
{
int result;
struct utsname utsname;
@@ -222,7 +223,7 @@ int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
/* For compatibility with older patches
* use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_X86_64 here.
*/
- *flags |= KEXEC_ARCH_DEFAULT;
+ info->kexec_flags |= KEXEC_ARCH_DEFAULT;
}
else {
fprintf(stderr, "Unsupported machine type: %s\n",
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 4d1a3db..fd66e15 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -39,8 +39,8 @@
#include "kexec-sha256.h"
#include <arch/options.h>
-static unsigned long long mem_min = 0;
-static unsigned long long mem_max = ULONG_MAX;
+unsigned long long mem_min = 0;
+unsigned long long mem_max = ULONG_MAX;
void die(char *fmt, ...)
{
@@ -508,6 +508,8 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
info.segment = NULL;
info.nr_segments = 0;
info.entry = NULL;
+ info.backup_start = 0;
+ info.kexec_flags = kexec_flags;
result = 0;
if (argc - fileind <= 0) {
@@ -523,7 +525,8 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
kernel_buf, kernel_size);
#endif
- if (get_memory_ranges(&memory_range, &memory_ranges) < 0) {
+ if (get_memory_ranges(&memory_range, &memory_ranges,
+ info.kexec_flags) < 0) {
fprintf(stderr, "Could not get memory layout\n");
return -1;
}
@@ -565,7 +568,7 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
return -1;
}
/* If we are not in native mode setup an appropriate trampoline */
- if (arch_compat_trampoline(&info, &kexec_flags) < 0) {
+ if (arch_compat_trampoline(&info) < 0) {
return -1;
}
/* Verify all of the segments load to a valid location in memory */
@@ -586,17 +589,17 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
update_purgatory(&info);
#if 0
fprintf(stderr, "kexec_load: entry = %p flags = %lx\n",
- info.entry, kexec_flags);
+ info.entry, info.kexec_flags);
print_segments(stderr, &info);
#endif
result = kexec_load(
- info.entry, info.nr_segments, info.segment, kexec_flags);
+ info.entry, info.nr_segments, info.segment, info.kexec_flags);
if (result != 0) {
/* The load failed, print some debugging information */
fprintf(stderr, "kexec_load failed: %s\n",
strerror(errno));
fprintf(stderr, "entry = %p flags = %lx\n",
- info.entry, kexec_flags);
+ info.entry, info.kexec_flags);
print_segments(stderr, &info);
}
return result;
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 10a95d6..a125cb7 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -91,6 +91,8 @@ do { \
} while(0)
#endif
+extern unsigned long long mem_min, mem_max;
+
struct kexec_segment {
const void *buf;
size_t bufsz;
@@ -112,10 +114,13 @@ struct kexec_info {
int nr_segments;
void *entry;
struct mem_ehdr rhdr;
+ unsigned long backup_start;
+ unsigned long kexec_flags;
};
void usage(void);
-int get_memory_ranges(struct memory_range **range, int *ranges);
+int get_memory_ranges(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags);
int valid_memory_range(unsigned long sstart, unsigned long send);
int valid_memory_segment(struct kexec_segment *segment);
void print_segments(FILE *file, struct kexec_info *info);
@@ -188,7 +193,7 @@ extern size_t purgatory_size;
void arch_usage(void);
int arch_process_options(int argc, char **argv);
-int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags);
+int arch_compat_trampoline(struct kexec_info *info);
void arch_update_purgatory(struct kexec_info *info);
#endif /* KEXEC_H */
diff --git a/purgatory/arch/i386/Makefile b/purgatory/arch/i386/Makefile
index 8af604c..97478f4 100644
--- a/purgatory/arch/i386/Makefile
+++ b/purgatory/arch/i386/Makefile
@@ -12,3 +12,4 @@ PURGATORY_C_SRCS+= purgatory/arch/i386/purgatory-x86.c
PURGATORY_C_SRCS+= purgatory/arch/i386/console-x86.c
PURGATORY_C_SRCS+= purgatory/arch/i386/vga.c
PURGATORY_C_SRCS+= purgatory/arch/i386/pic.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/crashdump_backup.c
diff --git a/purgatory/arch/i386/crashdump_backup.c b/purgatory/arch/i386/crashdump_backup.c
new file mode 100644
index 0000000..14e807f
--- /dev/null
+++ b/purgatory/arch/i386/crashdump_backup.c
@@ -0,0 +1,44 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Created by: Vivek goyal (vgoyal@in.ibm.com)
+ * Copyright (C) IBM Corporation, 2005. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#define BACKUP_REGION_SOURCE 0x00000000
+#define BACKUP_REGION_SIZE 0xa0000
+
+/* Backup region start gets set after /proc/iomem has been parsed. */
+uint32_t backup_start = 0;
+
+/* Backup first 640K of memory to backup region as reserved by kexec.
+ * Assuming first 640K has to be present on i386 machines and no address
+ * validity checks have to be performed. */
+
+void crashdump_backup_memory(void)
+{
+ void *dest, *src;
+
+ src = (void *) BACKUP_REGION_SOURCE;
+
+ if (backup_start) {
+ dest = (void *)(backup_start);
+ memcpy(dest, src, BACKUP_REGION_SIZE);
+ }
+}
diff --git a/purgatory/arch/i386/purgatory-x86.c b/purgatory/arch/i386/purgatory-x86.c
index 442358a..5ad0740 100644
--- a/purgatory/arch/i386/purgatory-x86.c
+++ b/purgatory/arch/i386/purgatory-x86.c
@@ -30,6 +30,7 @@ void x86_setup_cpu(void)
uint8_t reset_vga = 0;
uint8_t legacy_timer = 0;
uint8_t legacy_pic = 0;
+uint8_t panic_kernel = 0;
void setup_arch(void)
{
@@ -38,3 +39,9 @@ void setup_arch(void)
if (legacy_pic) x86_setup_legacy_pic();
/* if (legacy_timer) x86_setup_legacy_timer(); */
}
+
+/* This function can be used to execute after the SHA256 verification. */
+void post_verification_setup_arch(void)
+{
+ if (panic_kernel) crashdump_backup_memory();
+}
diff --git a/purgatory/arch/i386/purgatory-x86.h b/purgatory/arch/i386/purgatory-x86.h
index 4178b37..02039c9 100644
--- a/purgatory/arch/i386/purgatory-x86.h
+++ b/purgatory/arch/i386/purgatory-x86.h
@@ -4,5 +4,6 @@
void x86_reset_vga(void);
void x86_setup_legacy_pic(void);
void x86_setup_legacy_timer(void);
+void crashdump_backup_memory(void);
#endif /* PURGATORY_X86_H */
diff --git a/purgatory/arch/ia64/purgatory-ia64.c b/purgatory/arch/ia64/purgatory-ia64.c
index c10cbea..369e175 100644
--- a/purgatory/arch/ia64/purgatory-ia64.c
+++ b/purgatory/arch/ia64/purgatory-ia64.c
@@ -5,3 +5,9 @@ void setup_arch(void)
{
/* Nothing for now */
}
+
+/* This function can be used to execute after the SHA256 verification. */
+void post_verification_setup_arch(void)
+{
+ /* Nothing for now */
+}
diff --git a/purgatory/arch/ppc/purgatory-ppc.c b/purgatory/arch/ppc/purgatory-ppc.c
index ab4d941..077f495 100644
--- a/purgatory/arch/ppc/purgatory-ppc.c
+++ b/purgatory/arch/ppc/purgatory-ppc.c
@@ -5,3 +5,9 @@ void setup_arch(void)
{
/* Nothing for now */
}
+
+/* This function can be used to execute after the SHA256 verification. */
+void post_verification_setup_arch(void)
+{
+ /* Nothing for now */
+}
diff --git a/purgatory/arch/x86_64/purgatory-x86_64.c b/purgatory/arch/x86_64/purgatory-x86_64.c
index f839ab5..8a2387c 100644
--- a/purgatory/arch/x86_64/purgatory-x86_64.c
+++ b/purgatory/arch/x86_64/purgatory-x86_64.c
@@ -10,3 +10,9 @@ void setup_arch(void)
if (reset_vga) x86_reset_vga();
if (legacy_pic) x86_setup_legacy_pic();
}
+
+/* This function can be used to execute after the SHA256 verification. */
+void post_verification_setup_arch(void)
+{
+ /* Nothing for now */
+}
diff --git a/purgatory/include/purgatory.h b/purgatory/include/purgatory.h
index 93037f2..79ed5bf 100644
--- a/purgatory/include/purgatory.h
+++ b/purgatory/include/purgatory.h
@@ -4,5 +4,6 @@
void putchar(int ch);
void printf(const char *fmt, ...);
void setup_arch(void);
+void post_verification_setup_arch(void);
#endif /* PURGATORY_H */
diff --git a/purgatory/purgatory.c b/purgatory/purgatory.c
index 97fc638..ad0cac2 100644
--- a/purgatory/purgatory.c
+++ b/purgatory/purgatory.c
@@ -44,4 +44,5 @@ void purgatory(void)
printf("I'm in purgatory\n");
setup_arch();
verify_sha256_digest();
+ post_verification_setup_arch();
}