1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
From a49bd34de33ab54a1cbfdaae121dbaf99648d3b6 Mon Sep 17 00:00:00 2001
From: Julius Werner <jwerner@chromium.org>
Date: Wed, 20 Apr 2016 15:20:00 -0700
Subject: [PATCH] CHROMIUM: block: partitions: efi: Add support for IGNOREME
GPT signature
This patch adds support for a special GPT header signature marker (using
the string 'IGNOREME' instead of the spec's 'EFI PART'). This tells the
kernel to ignore this GPT completely and look at the other one instead.
Since the kernel always prefers the primary GPT anyway, all we really
need to do effectively is to check whether the primary GPT is marked
'IGNOREME' and force evaluation of the secondary one in that case.
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/340080
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
An earlier attempt to upstream an alternative solution:
https://patchwork.kernel.org/patch/8933841/
mka@: added missing param 'lba' to log message and resolved minor
conflicts.
BUG=chromium:941638, chrome-os-partner:52595
TEST=Booted on Minnie with 'IGNOREME' primary GPT
Change-Id: Ibaee639fac9fa2f04b8836ef153c95b7d0b045a4
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1531701
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
[rebase515(groeck):
Squash:
FIXUP: partitions/efi: Support non-standard GPT location
(API change)
]
Signed-off-by: Guenter Roeck <groeck@google.com>
---
block/partitions/efi.c | 33 +++++++++++++++++++++++----------
block/partitions/efi.h | 3 ++-
2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 7ca5c4c374d4..102d2587bdb3 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -328,23 +328,33 @@ static gpt_header *alloc_read_gpt_header(struct parsed_partitions *state,
* @lba: logical block address of the GPT header to test
* @gpt: GPT header ptr, filled on return.
* @ptes: PTEs ptr, filled on return.
+ * @ignored is filled on return with 1 if this is an IGNOREME GPT,
+ * 0 otherwise. May be NULL.
*
* Description: returns 1 if valid, 0 on error.
* If valid, returns pointers to newly allocated GPT header and PTEs.
*/
static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
- gpt_header **gpt, gpt_entry **ptes)
+ gpt_header **gpt, gpt_entry **ptes, int *ignored)
{
u32 crc, origcrc;
u64 lastlba, pt_size;
+ if (ignored)
+ *ignored = 0;
if (!ptes)
return 0;
if (!(*gpt = alloc_read_gpt_header(state, lba)))
return 0;
/* Check the GUID Partition Table signature */
- if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
+ if (le64_to_cpu((*gpt)->signature) == GPT_HEADER_SIGNATURE_IGNORED) {
+ pr_debug("GUID Partition Table at LBA %llu marked IGNOREME\n",
+ lba);
+ if (ignored)
+ *ignored = 1;
+ goto fail;
+ } else if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
pr_debug("GUID Partition Table Header signature is wrong:"
"%lld != %lld\n",
(unsigned long long)le64_to_cpu((*gpt)->signature),
@@ -581,7 +591,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
gpt_entry **ptes)
{
- int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
+ int good_pgpt = 0, good_agpt = 0, good_pmbr = 0, pgpt_ignored = 0;
gpt_header *pgpt = NULL, *agpt = NULL;
gpt_entry *pptes = NULL, *aptes = NULL;
legacy_mbr *legacymbr;
@@ -613,13 +623,14 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
}
good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA,
- &pgpt, &pptes);
+ &pgpt, &pptes, &pgpt_ignored);
if (good_pgpt)
good_agpt = is_gpt_valid(state,
le64_to_cpu(pgpt->alternate_lba),
- &agpt, &aptes);
- if (!good_agpt && force_gpt)
- good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
+ &agpt, &aptes, NULL);
+
+ if (!good_agpt && (force_gpt || pgpt_ignored))
+ good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes, NULL);
if (!good_agpt && force_gpt && fops->alternative_gpt_sector) {
sector_t agpt_sector;
@@ -628,14 +639,15 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
err = fops->alternative_gpt_sector(disk, &agpt_sector);
if (!err)
good_agpt = is_gpt_valid(state, agpt_sector,
- &agpt, &aptes);
+ &agpt, &aptes, NULL);
}
/* The obviously unsuccessful case */
if (!good_pgpt && !good_agpt)
goto fail;
- compare_gpts(pgpt, agpt, lastlba);
+ if (!pgpt_ignored)
+ compare_gpts(pgpt, agpt, lastlba);
/* The good cases */
if (good_pgpt) {
@@ -652,7 +664,8 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
*ptes = aptes;
kfree(pgpt);
kfree(pptes);
- pr_warn("Primary GPT is invalid, using alternate GPT.\n");
+ pr_warn("Primary GPT is %s, using alternate GPT.\n",
+ pgpt_ignored ? "being ignored" : "invalid");
return 1;
}
diff --git a/block/partitions/efi.h b/block/partitions/efi.h
index 8cc2b88d0aa8..fcf65ebbaa85 100644
--- a/block/partitions/efi.h
+++ b/block/partitions/efi.h
@@ -27,7 +27,8 @@
#define GPT_MBR_PROTECTIVE 1
#define GPT_MBR_HYBRID 2
-#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
+#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL /* 'EFI PART' */
+#define GPT_HEADER_SIGNATURE_IGNORED 0x454d45524f4e4749ULL /* 'IGNOREME' */
#define GPT_HEADER_REVISION_V1 0x00010000
#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
--
2.36.1
|