162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * purgatory: Runs between two kernels 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014 Red Hat Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: 862306a36Sopenharmony_ci * Vivek Goyal <vgoyal@redhat.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/bug.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/types.h> 1462306a36Sopenharmony_ci#include <crypto/sha2.h> 1562306a36Sopenharmony_ci#include <asm/purgatory.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "../boot/compressed/error.h" 1862306a36Sopenharmony_ci#include "../boot/string.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciu8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory"); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistruct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory"); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic int verify_sha256_digest(void) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct kexec_sha_region *ptr, *end; 2762306a36Sopenharmony_ci u8 digest[SHA256_DIGEST_SIZE]; 2862306a36Sopenharmony_ci struct sha256_state sctx; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci sha256_init(&sctx); 3162306a36Sopenharmony_ci end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci for (ptr = purgatory_sha_regions; ptr < end; ptr++) 3462306a36Sopenharmony_ci sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci sha256_final(&sctx, digest); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci if (memcmp(digest, purgatory_sha256_digest, sizeof(digest))) 3962306a36Sopenharmony_ci return 1; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci return 0; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_civoid purgatory(void) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci int ret; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci ret = verify_sha256_digest(); 4962306a36Sopenharmony_ci if (ret) { 5062306a36Sopenharmony_ci /* loop forever */ 5162306a36Sopenharmony_ci for (;;) 5262306a36Sopenharmony_ci ; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * Defined in order to reuse memcpy() and memset() from 5862306a36Sopenharmony_ci * arch/x86/boot/compressed/string.c 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_civoid warn(const char *msg) {} 61