xref: /openbmc/linux/arch/riscv/purgatory/purgatory.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1*736e30afSLi Zhengyu // SPDX-License-Identifier: GPL-2.0-only
2*736e30afSLi Zhengyu /*
3*736e30afSLi Zhengyu  * purgatory: Runs between two kernels
4*736e30afSLi Zhengyu  *
5*736e30afSLi Zhengyu  * Copyright (C) 2022 Huawei Technologies Co, Ltd.
6*736e30afSLi Zhengyu  *
7*736e30afSLi Zhengyu  * Author: Li Zhengyu (lizhengyu3@huawei.com)
8*736e30afSLi Zhengyu  *
9*736e30afSLi Zhengyu  */
10*736e30afSLi Zhengyu 
11*736e30afSLi Zhengyu #include <linux/purgatory.h>
12*736e30afSLi Zhengyu #include <linux/kernel.h>
13*736e30afSLi Zhengyu #include <linux/string.h>
14*736e30afSLi Zhengyu #include <asm/string.h>
15*736e30afSLi Zhengyu 
16*736e30afSLi Zhengyu u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory");
17*736e30afSLi Zhengyu 
18*736e30afSLi Zhengyu struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory");
19*736e30afSLi Zhengyu 
verify_sha256_digest(void)20*736e30afSLi Zhengyu static int verify_sha256_digest(void)
21*736e30afSLi Zhengyu {
22*736e30afSLi Zhengyu 	struct kexec_sha_region *ptr, *end;
23*736e30afSLi Zhengyu 	struct sha256_state ss;
24*736e30afSLi Zhengyu 	u8 digest[SHA256_DIGEST_SIZE];
25*736e30afSLi Zhengyu 
26*736e30afSLi Zhengyu 	sha256_init(&ss);
27*736e30afSLi Zhengyu 	end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
28*736e30afSLi Zhengyu 	for (ptr = purgatory_sha_regions; ptr < end; ptr++)
29*736e30afSLi Zhengyu 		sha256_update(&ss, (uint8_t *)(ptr->start), ptr->len);
30*736e30afSLi Zhengyu 	sha256_final(&ss, digest);
31*736e30afSLi Zhengyu 	if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)) != 0)
32*736e30afSLi Zhengyu 		return 1;
33*736e30afSLi Zhengyu 	return 0;
34*736e30afSLi Zhengyu }
35*736e30afSLi Zhengyu 
36*736e30afSLi Zhengyu /* workaround for a warning with -Wmissing-prototypes */
37*736e30afSLi Zhengyu void purgatory(void);
38*736e30afSLi Zhengyu 
purgatory(void)39*736e30afSLi Zhengyu void purgatory(void)
40*736e30afSLi Zhengyu {
41*736e30afSLi Zhengyu 	if (verify_sha256_digest())
42*736e30afSLi Zhengyu 		for (;;)
43*736e30afSLi Zhengyu 			/* loop forever */
44*736e30afSLi Zhengyu 			;
45*736e30afSLi Zhengyu }
46