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 Goyalstatic 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 Goyalvoid 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)60void warn(const char *msg) {} 61