1
2
3
4
5
6
7
8#define pr_fmt(fmt) "efi: " fmt
9
10#include <linux/slab.h>
11#include <linux/mutex.h>
12#include <linux/highmem.h>
13#include <linux/efi.h>
14#include <linux/vmalloc.h>
15#include <asm/io.h>
16
17typedef struct {
18 u64 length;
19 u64 data;
20} efi_capsule_block_desc_t;
21
22static bool capsule_pending;
23static bool stop_capsules;
24static int efi_reset_type = -1;
25
26
27
28
29
30static DEFINE_MUTEX(capsule_mutex);
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50bool efi_capsule_pending(int *reset_type)
51{
52 if (!capsule_pending)
53 return false;
54
55 if (reset_type)
56 *reset_type = efi_reset_type;
57
58 return true;
59}
60
61
62
63
64
65
66
67
68
69#define EFI_CAPSULE_SUPPORTED_FLAG_MASK \
70 (EFI_CAPSULE_PERSIST_ACROSS_RESET | EFI_CAPSULE_POPULATE_SYSTEM_TABLE)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85int efi_capsule_supported(efi_guid_t guid, u32 flags, size_t size, int *reset)
86{
87 efi_capsule_header_t capsule;
88 efi_capsule_header_t *cap_list[] = { &capsule };
89 efi_status_t status;
90 u64 max_size;
91
92 if (flags & ~EFI_CAPSULE_SUPPORTED_FLAG_MASK)
93 return -EINVAL;
94
95 capsule.headersize = capsule.imagesize = sizeof(capsule);
96 memcpy(&capsule.guid, &guid, sizeof(efi_guid_t));
97 capsule.flags = flags;
98
99 status = efi.query_capsule_caps(cap_list, 1, &max_size, reset);
100 if (status != EFI_SUCCESS)
101 return efi_status_to_err(status);
102
103 if (size > max_size)
104 return -ENOSPC;
105
106 return 0;
107}
108EXPORT_SYMBOL_GPL(efi_capsule_supported);
109
110
111
112
113
114
115#define SGLIST_PER_PAGE ((PAGE_SIZE / sizeof(efi_capsule_block_desc_t)) - 1)
116
117
118
119
120
121static inline unsigned int sg_pages_num(unsigned int count)
122{
123 return DIV_ROUND_UP(count, SGLIST_PER_PAGE);
124}
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141static int
142efi_capsule_update_locked(efi_capsule_header_t *capsule,
143 struct page **sg_pages, int reset)
144{
145 efi_physical_addr_t sglist_phys;
146 efi_status_t status;
147
148 lockdep_assert_held(&capsule_mutex);
149
150
151
152
153
154 if (efi_reset_type >= 0 && efi_reset_type != reset) {
155 pr_err("Conflicting capsule reset type %d (%d).\n",
156 reset, efi_reset_type);
157 return -EINVAL;
158 }
159
160
161
162
163
164
165
166 if (unlikely(stop_capsules)) {
167 pr_warn("Capsule update raced with reboot, aborting.\n");
168 return -EINVAL;
169 }
170
171 sglist_phys = page_to_phys(sg_pages[0]);
172
173 status = efi.update_capsule(&capsule, 1, sglist_phys);
174 if (status == EFI_SUCCESS) {
175 capsule_pending = true;
176 efi_reset_type = reset;
177 }
178
179 return efi_status_to_err(status);
180}
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
216{
217 u32 imagesize = capsule->imagesize;
218 efi_guid_t guid = capsule->guid;
219 unsigned int count, sg_count;
220 u32 flags = capsule->flags;
221 struct page **sg_pages;
222 int rv, reset_type;
223 int i, j;
224
225 rv = efi_capsule_supported(guid, flags, imagesize, &reset_type);
226 if (rv)
227 return rv;
228
229 count = DIV_ROUND_UP(imagesize, PAGE_SIZE);
230 sg_count = sg_pages_num(count);
231
232 sg_pages = kcalloc(sg_count, sizeof(*sg_pages), GFP_KERNEL);
233 if (!sg_pages)
234 return -ENOMEM;
235
236 for (i = 0; i < sg_count; i++) {
237 sg_pages[i] = alloc_page(GFP_KERNEL);
238 if (!sg_pages[i]) {
239 rv = -ENOMEM;
240 goto out;
241 }
242 }
243
244 for (i = 0; i < sg_count; i++) {
245 efi_capsule_block_desc_t *sglist;
246
247 sglist = kmap(sg_pages[i]);
248
249 for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) {
250 u64 sz = min_t(u64, imagesize,
251 PAGE_SIZE - (u64)*pages % PAGE_SIZE);
252
253 sglist[j].length = sz;
254 sglist[j].data = *pages++;
255
256 imagesize -= sz;
257 count--;
258 }
259
260
261 sglist[j].length = 0;
262
263 if (i + 1 == sg_count)
264 sglist[j].data = 0;
265 else
266 sglist[j].data = page_to_phys(sg_pages[i + 1]);
267
268 kunmap(sg_pages[i]);
269 }
270
271 mutex_lock(&capsule_mutex);
272 rv = efi_capsule_update_locked(capsule, sg_pages, reset_type);
273 mutex_unlock(&capsule_mutex);
274
275out:
276 for (i = 0; rv && i < sg_count; i++) {
277 if (sg_pages[i])
278 __free_page(sg_pages[i]);
279 }
280
281 kfree(sg_pages);
282 return rv;
283}
284EXPORT_SYMBOL_GPL(efi_capsule_update);
285
286static int capsule_reboot_notify(struct notifier_block *nb, unsigned long event, void *cmd)
287{
288 mutex_lock(&capsule_mutex);
289 stop_capsules = true;
290 mutex_unlock(&capsule_mutex);
291
292 return NOTIFY_DONE;
293}
294
295static struct notifier_block capsule_reboot_nb = {
296 .notifier_call = capsule_reboot_notify,
297};
298
299static int __init capsule_reboot_register(void)
300{
301 return register_reboot_notifier(&capsule_reboot_nb);
302}
303core_initcall(capsule_reboot_register);
304