diff options
-rw-r--r-- | arch/powerpc/purgatory/trampoline.S | 12 | ||||
-rw-r--r-- | arch/x86/include/asm/purgatory.h | 20 | ||||
-rw-r--r-- | arch/x86/kernel/machine_kexec_64.c | 9 | ||||
-rw-r--r-- | arch/x86/purgatory/purgatory.c | 35 | ||||
-rw-r--r-- | arch/x86/purgatory/purgatory.h | 8 | ||||
-rw-r--r-- | arch/x86/purgatory/setup-x86_64.S | 2 | ||||
-rw-r--r-- | arch/x86/purgatory/sha256.h | 1 | ||||
-rw-r--r-- | include/linux/purgatory.h | 23 | ||||
-rw-r--r-- | kernel/kexec_file.c | 8 | ||||
-rw-r--r-- | kernel/kexec_internal.h | 6 |
10 files changed, 78 insertions, 46 deletions
diff --git a/arch/powerpc/purgatory/trampoline.S b/arch/powerpc/purgatory/trampoline.S index f9760ccf4032..3696ea6c4826 100644 --- a/arch/powerpc/purgatory/trampoline.S +++ b/arch/powerpc/purgatory/trampoline.S | |||
@@ -116,13 +116,13 @@ dt_offset: | |||
116 | 116 | ||
117 | .data | 117 | .data |
118 | .balign 8 | 118 | .balign 8 |
119 | .globl sha256_digest | 119 | .globl purgatory_sha256_digest |
120 | sha256_digest: | 120 | purgatory_sha256_digest: |
121 | .skip 32 | 121 | .skip 32 |
122 | .size sha256_digest, . - sha256_digest | 122 | .size purgatory_sha256_digest, . - purgatory_sha256_digest |
123 | 123 | ||
124 | .balign 8 | 124 | .balign 8 |
125 | .globl sha_regions | 125 | .globl purgatory_sha_regions |
126 | sha_regions: | 126 | purgatory_sha_regions: |
127 | .skip 8 * 2 * 16 | 127 | .skip 8 * 2 * 16 |
128 | .size sha_regions, . - sha_regions | 128 | .size purgatory_sha_regions, . - purgatory_sha_regions |
diff --git a/arch/x86/include/asm/purgatory.h b/arch/x86/include/asm/purgatory.h new file mode 100644 index 000000000000..d7da2729903d --- /dev/null +++ b/arch/x86/include/asm/purgatory.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #ifndef _ASM_X86_PURGATORY_H | ||
2 | #define _ASM_X86_PURGATORY_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | #include <linux/purgatory.h> | ||
6 | |||
7 | extern void purgatory(void); | ||
8 | /* | ||
9 | * These forward declarations serve two purposes: | ||
10 | * | ||
11 | * 1) Make sparse happy when checking arch/purgatory | ||
12 | * 2) Document that these are required to be global so the symbol | ||
13 | * lookup in kexec works | ||
14 | */ | ||
15 | extern unsigned long purgatory_backup_dest; | ||
16 | extern unsigned long purgatory_backup_src; | ||
17 | extern unsigned long purgatory_backup_sz; | ||
18 | #endif /* __ASSEMBLY__ */ | ||
19 | |||
20 | #endif /* _ASM_PURGATORY_H */ | ||
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 307b1f4543de..857cdbd02867 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c | |||
@@ -194,19 +194,22 @@ static int arch_update_purgatory(struct kimage *image) | |||
194 | 194 | ||
195 | /* Setup copying of backup region */ | 195 | /* Setup copying of backup region */ |
196 | if (image->type == KEXEC_TYPE_CRASH) { | 196 | if (image->type == KEXEC_TYPE_CRASH) { |
197 | ret = kexec_purgatory_get_set_symbol(image, "backup_dest", | 197 | ret = kexec_purgatory_get_set_symbol(image, |
198 | "purgatory_backup_dest", | ||
198 | &image->arch.backup_load_addr, | 199 | &image->arch.backup_load_addr, |
199 | sizeof(image->arch.backup_load_addr), 0); | 200 | sizeof(image->arch.backup_load_addr), 0); |
200 | if (ret) | 201 | if (ret) |
201 | return ret; | 202 | return ret; |
202 | 203 | ||
203 | ret = kexec_purgatory_get_set_symbol(image, "backup_src", | 204 | ret = kexec_purgatory_get_set_symbol(image, |
205 | "purgatory_backup_src", | ||
204 | &image->arch.backup_src_start, | 206 | &image->arch.backup_src_start, |
205 | sizeof(image->arch.backup_src_start), 0); | 207 | sizeof(image->arch.backup_src_start), 0); |
206 | if (ret) | 208 | if (ret) |
207 | return ret; | 209 | return ret; |
208 | 210 | ||
209 | ret = kexec_purgatory_get_set_symbol(image, "backup_sz", | 211 | ret = kexec_purgatory_get_set_symbol(image, |
212 | "purgatory_backup_sz", | ||
210 | &image->arch.backup_src_sz, | 213 | &image->arch.backup_src_sz, |
211 | sizeof(image->arch.backup_src_sz), 0); | 214 | sizeof(image->arch.backup_src_sz), 0); |
212 | if (ret) | 215 | if (ret) |
diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c index b6d5c8946e66..470edad96bb9 100644 --- a/arch/x86/purgatory/purgatory.c +++ b/arch/x86/purgatory/purgatory.c | |||
@@ -10,22 +10,19 @@ | |||
10 | * Version 2. See the file COPYING for more details. | 10 | * Version 2. See the file COPYING for more details. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/bug.h> | ||
14 | #include <asm/purgatory.h> | ||
15 | |||
13 | #include "sha256.h" | 16 | #include "sha256.h" |
14 | #include "purgatory.h" | ||
15 | #include "../boot/string.h" | 17 | #include "../boot/string.h" |
16 | 18 | ||
17 | struct sha_region { | 19 | unsigned long purgatory_backup_dest __section(.kexec-purgatory); |
18 | unsigned long start; | 20 | unsigned long purgatory_backup_src __section(.kexec-purgatory); |
19 | unsigned long len; | 21 | unsigned long purgatory_backup_sz __section(.kexec-purgatory); |
20 | }; | ||
21 | |||
22 | static unsigned long backup_dest; | ||
23 | static unsigned long backup_src; | ||
24 | static unsigned long backup_sz; | ||
25 | 22 | ||
26 | static u8 sha256_digest[SHA256_DIGEST_SIZE] = { 0 }; | 23 | u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(.kexec-purgatory); |
27 | 24 | ||
28 | struct sha_region sha_regions[16] = {}; | 25 | struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(.kexec-purgatory); |
29 | 26 | ||
30 | /* | 27 | /* |
31 | * On x86, second kernel requries first 640K of memory to boot. Copy | 28 | * On x86, second kernel requries first 640K of memory to boot. Copy |
@@ -34,26 +31,28 @@ struct sha_region sha_regions[16] = {}; | |||
34 | */ | 31 | */ |
35 | static int copy_backup_region(void) | 32 | static int copy_backup_region(void) |
36 | { | 33 | { |
37 | if (backup_dest) | 34 | if (purgatory_backup_dest) { |
38 | memcpy((void *)backup_dest, (void *)backup_src, backup_sz); | 35 | memcpy((void *)purgatory_backup_dest, |
39 | 36 | (void *)purgatory_backup_src, purgatory_backup_sz); | |
37 | } | ||
40 | return 0; | 38 | return 0; |
41 | } | 39 | } |
42 | 40 | ||
43 | static int verify_sha256_digest(void) | 41 | static int verify_sha256_digest(void) |
44 | { | 42 | { |
45 | struct sha_region *ptr, *end; | 43 | struct kexec_sha_region *ptr, *end; |
46 | u8 digest[SHA256_DIGEST_SIZE]; | 44 | u8 digest[SHA256_DIGEST_SIZE]; |
47 | struct sha256_state sctx; | 45 | struct sha256_state sctx; |
48 | 46 | ||
49 | sha256_init(&sctx); | 47 | sha256_init(&sctx); |
50 | end = &sha_regions[sizeof(sha_regions)/sizeof(sha_regions[0])]; | 48 | end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions); |
51 | for (ptr = sha_regions; ptr < end; ptr++) | 49 | |
50 | for (ptr = purgatory_sha_regions; ptr < end; ptr++) | ||
52 | sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len); | 51 | sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len); |
53 | 52 | ||
54 | sha256_final(&sctx, digest); | 53 | sha256_final(&sctx, digest); |
55 | 54 | ||
56 | if (memcmp(digest, sha256_digest, sizeof(digest))) | 55 | if (memcmp(digest, purgatory_sha256_digest, sizeof(digest))) |
57 | return 1; | 56 | return 1; |
58 | 57 | ||
59 | return 0; | 58 | return 0; |
diff --git a/arch/x86/purgatory/purgatory.h b/arch/x86/purgatory/purgatory.h deleted file mode 100644 index e2e365a6c192..000000000000 --- a/arch/x86/purgatory/purgatory.h +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #ifndef PURGATORY_H | ||
2 | #define PURGATORY_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | extern void purgatory(void); | ||
6 | #endif /* __ASSEMBLY__ */ | ||
7 | |||
8 | #endif /* PURGATORY_H */ | ||
diff --git a/arch/x86/purgatory/setup-x86_64.S b/arch/x86/purgatory/setup-x86_64.S index f90e9dfa90bb..dfae9b9e60b5 100644 --- a/arch/x86/purgatory/setup-x86_64.S +++ b/arch/x86/purgatory/setup-x86_64.S | |||
@@ -9,7 +9,7 @@ | |||
9 | * This source code is licensed under the GNU General Public License, | 9 | * This source code is licensed under the GNU General Public License, |
10 | * Version 2. See the file COPYING for more details. | 10 | * Version 2. See the file COPYING for more details. |
11 | */ | 11 | */ |
12 | #include "purgatory.h" | 12 | #include <asm/purgatory.h> |
13 | 13 | ||
14 | .text | 14 | .text |
15 | .globl purgatory_start | 15 | .globl purgatory_start |
diff --git a/arch/x86/purgatory/sha256.h b/arch/x86/purgatory/sha256.h index bd15a4127735..2867d9825a57 100644 --- a/arch/x86/purgatory/sha256.h +++ b/arch/x86/purgatory/sha256.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #ifndef SHA256_H | 10 | #ifndef SHA256_H |
11 | #define SHA256_H | 11 | #define SHA256_H |
12 | 12 | ||
13 | |||
14 | #include <linux/types.h> | 13 | #include <linux/types.h> |
15 | #include <crypto/sha.h> | 14 | #include <crypto/sha.h> |
16 | 15 | ||
diff --git a/include/linux/purgatory.h b/include/linux/purgatory.h new file mode 100644 index 000000000000..d60d4e278609 --- /dev/null +++ b/include/linux/purgatory.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef _LINUX_PURGATORY_H | ||
2 | #define _LINUX_PURGATORY_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <crypto/sha.h> | ||
6 | #include <uapi/linux/kexec.h> | ||
7 | |||
8 | struct kexec_sha_region { | ||
9 | unsigned long start; | ||
10 | unsigned long len; | ||
11 | }; | ||
12 | |||
13 | /* | ||
14 | * These forward declarations serve two purposes: | ||
15 | * | ||
16 | * 1) Make sparse happy when checking arch/purgatory | ||
17 | * 2) Document that these are required to be global so the symbol | ||
18 | * lookup in kexec works | ||
19 | */ | ||
20 | extern struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX]; | ||
21 | extern u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE]; | ||
22 | |||
23 | #endif | ||
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index b56a558e406d..b118735fea9d 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c | |||
@@ -614,13 +614,13 @@ static int kexec_calculate_store_digests(struct kimage *image) | |||
614 | ret = crypto_shash_final(desc, digest); | 614 | ret = crypto_shash_final(desc, digest); |
615 | if (ret) | 615 | if (ret) |
616 | goto out_free_digest; | 616 | goto out_free_digest; |
617 | ret = kexec_purgatory_get_set_symbol(image, "sha_regions", | 617 | ret = kexec_purgatory_get_set_symbol(image, "purgatory_sha_regions", |
618 | sha_regions, sha_region_sz, 0); | 618 | sha_regions, sha_region_sz, 0); |
619 | if (ret) | 619 | if (ret) |
620 | goto out_free_digest; | 620 | goto out_free_digest; |
621 | 621 | ||
622 | ret = kexec_purgatory_get_set_symbol(image, "sha256_digest", | 622 | ret = kexec_purgatory_get_set_symbol(image, "purgatory_sha256_digest", |
623 | digest, SHA256_DIGEST_SIZE, 0); | 623 | digest, SHA256_DIGEST_SIZE, 0); |
624 | if (ret) | 624 | if (ret) |
625 | goto out_free_digest; | 625 | goto out_free_digest; |
626 | } | 626 | } |
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h index 4cef7e4706b0..799a8a452187 100644 --- a/kernel/kexec_internal.h +++ b/kernel/kexec_internal.h | |||
@@ -15,11 +15,7 @@ int kimage_is_destination_range(struct kimage *image, | |||
15 | extern struct mutex kexec_mutex; | 15 | extern struct mutex kexec_mutex; |
16 | 16 | ||
17 | #ifdef CONFIG_KEXEC_FILE | 17 | #ifdef CONFIG_KEXEC_FILE |
18 | struct kexec_sha_region { | 18 | #include <linux/purgatory.h> |
19 | unsigned long start; | ||
20 | unsigned long len; | ||
21 | }; | ||
22 | |||
23 | void kimage_file_post_load_cleanup(struct kimage *image); | 19 | void kimage_file_post_load_cleanup(struct kimage *image); |
24 | #else /* CONFIG_KEXEC_FILE */ | 20 | #else /* CONFIG_KEXEC_FILE */ |
25 | static inline void kimage_file_post_load_cleanup(struct kimage *image) { } | 21 | static inline void kimage_file_post_load_cleanup(struct kimage *image) { } |