18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * purgatory: Runs between two kernels 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Red Hat Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: 88c2ecf20Sopenharmony_ci * Vivek Goyal <vgoyal@redhat.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/bug.h> 128c2ecf20Sopenharmony_ci#include <crypto/sha.h> 138c2ecf20Sopenharmony_ci#include <asm/purgatory.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "../boot/string.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciu8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory"); 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory"); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic int verify_sha256_digest(void) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct kexec_sha_region *ptr, *end; 248c2ecf20Sopenharmony_ci u8 digest[SHA256_DIGEST_SIZE]; 258c2ecf20Sopenharmony_ci struct sha256_state sctx; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci sha256_init(&sctx); 288c2ecf20Sopenharmony_ci end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci for (ptr = purgatory_sha_regions; ptr < end; ptr++) 318c2ecf20Sopenharmony_ci sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci sha256_final(&sctx, digest); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (memcmp(digest, purgatory_sha256_digest, sizeof(digest))) 368c2ecf20Sopenharmony_ci return 1; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci return 0; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_civoid purgatory(void) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci int ret; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci ret = verify_sha256_digest(); 468c2ecf20Sopenharmony_ci if (ret) { 478c2ecf20Sopenharmony_ci /* loop forever */ 488c2ecf20Sopenharmony_ci for (;;) 498c2ecf20Sopenharmony_ci ; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* 548c2ecf20Sopenharmony_ci * Defined in order to reuse memcpy() and memset() from 558c2ecf20Sopenharmony_ci * arch/x86/boot/compressed/string.c 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_civoid warn(const char *msg) {} 58