xref: /openbmc/linux/arch/x86/purgatory/purgatory.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
140b0b3f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28fc5b4d4SVivek Goyal /*
38fc5b4d4SVivek Goyal  * purgatory: Runs between two kernels
48fc5b4d4SVivek Goyal  *
58fc5b4d4SVivek Goyal  * Copyright (C) 2014 Red Hat Inc.
68fc5b4d4SVivek Goyal  *
78fc5b4d4SVivek Goyal  * Author:
88fc5b4d4SVivek Goyal  *       Vivek Goyal <vgoyal@redhat.com>
98fc5b4d4SVivek Goyal  */
108fc5b4d4SVivek Goyal 
1140c50c1fSThomas Gleixner #include <linux/bug.h>
12*f39650deSAndy Shevchenko #include <linux/kernel.h>
13*f39650deSAndy Shevchenko #include <linux/types.h>
14a24d22b2SEric Biggers #include <crypto/sha2.h>
1540c50c1fSThomas Gleixner #include <asm/purgatory.h>
1640c50c1fSThomas Gleixner 
178fc5b4d4SVivek Goyal #include "../boot/compressed/error.h"
188fc5b4d4SVivek Goyal #include "../boot/string.h"
1933def849SJoe Perches 
208fc5b4d4SVivek Goyal u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory");
2133def849SJoe Perches 
228fc5b4d4SVivek Goyal struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory");
2372042a8cSTobin C. Harding 
verify_sha256_digest(void)248fc5b4d4SVivek Goyal static int verify_sha256_digest(void)
2540c50c1fSThomas Gleixner {
268fc5b4d4SVivek Goyal 	struct kexec_sha_region *ptr, *end;
278fc5b4d4SVivek Goyal 	u8 digest[SHA256_DIGEST_SIZE];
288fc5b4d4SVivek Goyal 	struct sha256_state sctx;
298fc5b4d4SVivek Goyal 
3040c50c1fSThomas Gleixner 	sha256_init(&sctx);
3140c50c1fSThomas Gleixner 	end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
3240c50c1fSThomas Gleixner 
338fc5b4d4SVivek Goyal 	for (ptr = purgatory_sha_regions; ptr < end; ptr++)
348fc5b4d4SVivek Goyal 		sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
358fc5b4d4SVivek Goyal 
368fc5b4d4SVivek Goyal 	sha256_final(&sctx, digest);
3740c50c1fSThomas Gleixner 
388fc5b4d4SVivek Goyal 	if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)))
398fc5b4d4SVivek Goyal 		return 1;
408fc5b4d4SVivek Goyal 
418fc5b4d4SVivek Goyal 	return 0;
428fc5b4d4SVivek Goyal }
438fc5b4d4SVivek Goyal 
purgatory(void)448fc5b4d4SVivek Goyal void purgatory(void)
458fc5b4d4SVivek Goyal {
468fc5b4d4SVivek Goyal 	int ret;
478fc5b4d4SVivek Goyal 
488fc5b4d4SVivek Goyal 	ret = verify_sha256_digest();
498fc5b4d4SVivek Goyal 	if (ret) {
508fc5b4d4SVivek Goyal 		/* loop forever */
518fc5b4d4SVivek Goyal 		for (;;)
528fc5b4d4SVivek Goyal 			;
538fc5b4d4SVivek Goyal 	}
544ce97317SNick Desaulniers }
554ce97317SNick Desaulniers 
564ce97317SNick Desaulniers /*
574ce97317SNick Desaulniers  * Defined in order to reuse memcpy() and memset() from
584ce97317SNick Desaulniers  * arch/x86/boot/compressed/string.c
594ce97317SNick Desaulniers  */
warn(const char * msg)60 void warn(const char *msg) {}
61