]> git.proxmox.com Git - efi-boot-shim.git/blame - shim.c
Import upstream version 0.9+1474479173.6c180c6
[efi-boot-shim.git] / shim.c
CommitLineData
f898777d
MG
1/*
2 * shim - trivial UEFI first-stage bootloader
3 *
4 * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Significant portions of this code are derived from Tianocore
32 * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
33 * Corporation.
34 */
35
b2fe1780
MG
36#include <efi.h>
37#include <efilib.h>
7f055335 38#include <Library/BaseCryptLib.h>
b2fe1780 39#include "PeImage.h"
f4b24734 40#include "shim.h"
1c595706 41#include "netboot.h"
62f0afa2 42#include "httpboot.h"
ef8c9962 43#include "shim_cert.h"
cbef697a 44#include "replacements.h"
d3819813 45#include "tpm.h"
6e1bd3dc 46#include "ucs2.h"
b2fe1780 47
53862dda 48#include "guid.h"
7f0208a0 49#include "variables.h"
53862dda 50#include "efiauthenticated.h"
59dcd9d1 51#include "security_policy.h"
bc71a15e 52#include "console.h"
0fb089ee 53#include "version.h"
53862dda 54
62f0afa2
MTL
55#include <stdarg.h>
56#include <openssl/x509.h>
57#include <openssl/x509v3.h>
58
59#define FALLBACK L"\\fb" EFI_ARCH L".efi"
60#define MOK_MANAGER L"\\mm" EFI_ARCH L".efi"
61
62#define OID_EKU_MODSIGN "1.3.6.1.4.1.2312.16.1.2"
f898777d 63
7f055335 64static EFI_SYSTEM_TABLE *systab;
d3819813 65static EFI_HANDLE image_handle;
7f055335
MG
66static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
67
09e2c939
GCPL
68static CHAR16 *second_stage;
69static void *load_options;
70static UINT32 load_options_size;
e50cfe37
GCPL
71static UINT8 in_protocol;
72
73#define perror(fmt, ...) ({ \
74 UINTN __perror_ret = 0; \
631225fb 75 if (!in_protocol) \
e50cfe37
GCPL
76 __perror_ret = Print((fmt), ##__VA_ARGS__); \
77 __perror_ret; \
78 })
09e2c939 79
cb59de38
PJ
80EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
81
f898777d
MG
82/*
83 * The vendor certificate used for validating the second stage loader
84 */
a1f28635
PJ
85extern struct {
86 UINT32 vendor_cert_size;
87 UINT32 vendor_dbx_size;
88 UINT32 vendor_cert_offset;
89 UINT32 vendor_dbx_offset;
90} cert_table;
91
92UINT32 vendor_cert_size;
93UINT32 vendor_dbx_size;
94UINT8 *vendor_cert;
95UINT8 *vendor_dbx;
b2fe1780 96
cbef697a
PJ
97/*
98 * indicator of how an image has been verified
99 */
100verification_method_t verification_method;
101int loader_is_participating;
102
c13fc2f7
MG
103#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
104
e60f1181 105UINT8 user_insecure_mode;
47ebeb62 106UINT8 ignore_db;
9eaadb0d 107
c16548d0
MG
108typedef enum {
109 DATA_FOUND,
110 DATA_NOT_FOUND,
111 VAR_NOT_FOUND
112} CHECK_STATUS;
113
13422973
GCPL
114typedef struct {
115 UINT32 MokSize;
116 UINT8 *Mok;
117} MokListNode;
118
f898777d
MG
119/*
120 * Perform basic bounds checking of the intra-image pointers
121 */
47a9d2c9 122static void *ImageAddress (void *image, unsigned int size, unsigned int address)
b2fe1780 123{
f898777d
MG
124 if (address > size)
125 return NULL;
9d56c38f 126
f898777d
MG
127 return image + address;
128}
9d56c38f 129
afec82ac
PJ
130/* here's a chart:
131 * i686 x86_64 aarch64
132 * 64-on-64: nyet yes yes
133 * 64-on-32: nyet yes nyet
134 * 32-on-32: yes yes no
135 */
136static int
137allow_64_bit(void)
138{
139#if defined(__x86_64__) || defined(__aarch64__)
140 return 1;
141#elif defined(__i386__) || defined(__i686__)
142 /* Right now blindly assuming the kernel will correctly detect this
143 * and /halt the system/ if you're not really on a 64-bit cpu */
144 if (in_protocol)
145 return 1;
146 return 0;
147#else /* assuming everything else is 32-bit... */
148 return 0;
149#endif
150}
151
152static int
153allow_32_bit(void)
154{
155#if defined(__x86_64__)
156#if defined(ALLOW_32BIT_KERNEL_ON_X64)
157 if (in_protocol)
158 return 1;
159 return 0;
160#else
161 return 0;
162#endif
163#elif defined(__i386__) || defined(__i686__)
164 return 1;
165#elif defined(__arch64__)
166 return 0;
167#else /* assuming everything else is 32-bit... */
168 return 1;
169#endif
170}
171
172static int
173image_is_64_bit(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
174{
175 /* .Magic is the same offset in all cases */
176 if (PEHdr->Pe32Plus.OptionalHeader.Magic
177 == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC)
178 return 1;
179 return 0;
180}
181
182static const UINT16 machine_type =
183#if defined(__x86_64__)
184 IMAGE_FILE_MACHINE_X64;
185#elif defined(__aarch64__)
186 IMAGE_FILE_MACHINE_ARM64;
187#elif defined(__arm__)
188 IMAGE_FILE_MACHINE_ARMTHUMB_MIXED;
189#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
190 IMAGE_FILE_MACHINE_I386;
191#elif defined(__ia64__)
192 IMAGE_FILE_MACHINE_IA64;
193#else
194#error this architecture is not supported by shim
195#endif
196
197static int
198image_is_loadable(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
199{
200 /* If the machine type doesn't match the binary, bail, unless
201 * we're in an allowed 64-on-32 scenario */
202 if (PEHdr->Pe32.FileHeader.Machine != machine_type) {
203 if (!(machine_type == IMAGE_FILE_MACHINE_I386 &&
204 PEHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64 &&
205 allow_64_bit())) {
206 return 0;
207 }
208 }
209
210 /* If it's not a header type we recognize at all, bail */
211 switch (PEHdr->Pe32Plus.OptionalHeader.Magic) {
212 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
213 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
214 break;
215 default:
216 return 0;
217 }
218
219 /* and now just check for general 64-vs-32 compatibility */
220 if (image_is_64_bit(PEHdr)) {
221 if (allow_64_bit())
222 return 1;
223 } else {
224 if (allow_32_bit())
225 return 1;
226 }
227 return 0;
228}
229
f898777d
MG
230/*
231 * Perform the actual relocation
232 */
7db60bd8 233static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
a16340e3 234 EFI_IMAGE_SECTION_HEADER *Section,
486bf03e 235 void *orig, void *data)
f898777d
MG
236{
237 EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
238 UINT64 Adjust;
239 UINT16 *Reloc, *RelocEnd;
240 char *Fixup, *FixupBase, *FixupData = NULL;
241 UINT16 *Fixup16;
242 UINT32 *Fixup32;
243 UINT64 *Fixup64;
244 int size = context->ImageSize;
486bf03e 245 void *ImageEnd = (char *)orig + size;
a16340e3 246 int n = 0;
9d56c38f 247
afec82ac
PJ
248 if (image_is_64_bit(context->PEHdr))
249 context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)(unsigned long)data;
250 else
251 context->PEHdr->Pe32.OptionalHeader.ImageBase = (UINT32)(unsigned long)data;
7f055335 252
a16340e3
PJ
253 /* Alright, so here's how this works:
254 *
255 * context->RelocDir gives us two things:
256 * - the VA the table of base relocation blocks are (maybe) to be
257 * mapped at (RelocDir->VirtualAddress)
258 * - the virtual size (RelocDir->Size)
259 *
260 * The .reloc section (Section here) gives us some other things:
261 * - the name! kind of. (Section->Name)
262 * - the virtual size (Section->VirtualSize), which should be the same
263 * as RelocDir->Size
264 * - the virtual address (Section->VirtualAddress)
265 * - the file section size (Section->SizeOfRawData), which is
266 * a multiple of OptHdr->FileAlignment. Only useful for image
267 * validation, not really useful for iteration bounds.
268 * - the file address (Section->PointerToRawData)
269 * - a bunch of stuff we don't use that's 0 in our binaries usually
270 * - Flags (Section->Characteristics)
271 *
272 * and then the thing that's actually at the file address is an array
273 * of EFI_IMAGE_BASE_RELOCATION structs with some values packed behind
274 * them. The SizeOfBlock field of this structure includes the
275 * structure itself, and adding it to that structure's address will
276 * yield the next entry in the array.
277 */
278 RelocBase = ImageAddress(orig, size, Section->PointerToRawData);
279 /* RelocBaseEnd here is the address of the first entry /past/ the
280 * table. */
281 RelocBaseEnd = ImageAddress(orig, size, Section->PointerToRawData +
282 Section->Misc.VirtualSize);
283
284 if (!RelocBase && !RelocBaseEnd)
285 return EFI_SUCCESS;
9d56c38f 286
f898777d 287 if (!RelocBase || !RelocBaseEnd) {
e50cfe37 288 perror(L"Reloc table overflows binary\n");
f898777d 289 return EFI_UNSUPPORTED;
9d56c38f
MG
290 }
291
b6a12d99 292 Adjust = (UINTN)data - context->ImageAddress;
9d56c38f 293
a3beb2a6
PJ
294 if (Adjust == 0)
295 return EFI_SUCCESS;
296
f898777d
MG
297 while (RelocBase < RelocBaseEnd) {
298 Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
9d56c38f 299
a3beb2a6 300 if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > context->RelocDir->Size)) {
a16340e3 301 perror(L"Reloc %d block size %d is invalid\n", n, RelocBase->SizeOfBlock);
a3beb2a6
PJ
302 return EFI_UNSUPPORTED;
303 }
304
305 RelocEnd = (UINT16 *) ((char *) RelocBase + RelocBase->SizeOfBlock);
486bf03e 306 if ((void *)RelocEnd < orig || (void *)RelocEnd > ImageEnd) {
a16340e3 307 perror(L"Reloc %d entry overflows binary\n", n);
f898777d 308 return EFI_UNSUPPORTED;
9d56c38f
MG
309 }
310
7db60bd8 311 FixupBase = ImageAddress(data, size, RelocBase->VirtualAddress);
f898777d 312 if (!FixupBase) {
a16340e3 313 perror(L"Reloc %d Invalid fixupbase\n", n);
f898777d 314 return EFI_UNSUPPORTED;
9d56c38f 315 }
9d56c38f 316
f898777d
MG
317 while (Reloc < RelocEnd) {
318 Fixup = FixupBase + (*Reloc & 0xFFF);
319 switch ((*Reloc) >> 12) {
320 case EFI_IMAGE_REL_BASED_ABSOLUTE:
321 break;
9d56c38f 322
f898777d
MG
323 case EFI_IMAGE_REL_BASED_HIGH:
324 Fixup16 = (UINT16 *) Fixup;
325 *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
326 if (FixupData != NULL) {
327 *(UINT16 *) FixupData = *Fixup16;
328 FixupData = FixupData + sizeof (UINT16);
329 }
330 break;
9d56c38f 331
f898777d
MG
332 case EFI_IMAGE_REL_BASED_LOW:
333 Fixup16 = (UINT16 *) Fixup;
334 *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust);
335 if (FixupData != NULL) {
336 *(UINT16 *) FixupData = *Fixup16;
337 FixupData = FixupData + sizeof (UINT16);
338 }
339 break;
b2fe1780 340
f898777d
MG
341 case EFI_IMAGE_REL_BASED_HIGHLOW:
342 Fixup32 = (UINT32 *) Fixup;
343 *Fixup32 = *Fixup32 + (UINT32) Adjust;
344 if (FixupData != NULL) {
345 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
346 *(UINT32 *)FixupData = *Fixup32;
347 FixupData = FixupData + sizeof (UINT32);
348 }
349 break;
b2fe1780 350
f898777d
MG
351 case EFI_IMAGE_REL_BASED_DIR64:
352 Fixup64 = (UINT64 *) Fixup;
353 *Fixup64 = *Fixup64 + (UINT64) Adjust;
354 if (FixupData != NULL) {
355 FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64));
356 *(UINT64 *)(FixupData) = *Fixup64;
357 FixupData = FixupData + sizeof(UINT64);
358 }
359 break;
b2fe1780 360
f898777d 361 default:
a16340e3 362 perror(L"Reloc %d Unknown relocation\n", n);
f898777d
MG
363 return EFI_UNSUPPORTED;
364 }
365 Reloc += 1;
0e6b0195 366 }
f898777d 367 RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
a16340e3 368 n++;
7f055335 369 }
b2fe1780
MG
370
371 return EFI_SUCCESS;
372}
373
b8070380
GCPL
374static BOOLEAN verify_x509(UINT8 *Cert, UINTN CertSize)
375{
376 UINTN length;
377
378 if (!Cert || CertSize < 4)
379 return FALSE;
380
381 /*
382 * A DER encoding x509 certificate starts with SEQUENCE(0x30),
383 * the number of length bytes, and the number of value bytes.
384 * The size of a x509 certificate is usually between 127 bytes
385 * and 64KB. For convenience, assume the number of value bytes
386 * is 2, i.e. the second byte is 0x82.
387 */
388 if (Cert[0] != 0x30 || Cert[1] != 0x82)
389 return FALSE;
390
391 length = Cert[2]<<8 | Cert[3];
392 if (length != (CertSize - 4))
393 return FALSE;
394
395 return TRUE;
396}
397
62f0afa2
MTL
398static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize)
399{
400 X509 *x509;
401 CONST UINT8 *Temp = Cert;
402 EXTENDED_KEY_USAGE *eku;
403 ASN1_OBJECT *module_signing;
404
405 module_signing = OBJ_nid2obj(OBJ_create(OID_EKU_MODSIGN, NULL, NULL));
406
407 x509 = d2i_X509 (NULL, &Temp, (long) CertSize);
408 if (x509 != NULL) {
409 eku = X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL);
410
411 if (eku) {
412 int i = 0;
413 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
414 ASN1_OBJECT *key_usage = sk_ASN1_OBJECT_value(eku, i);
415
416 if (OBJ_cmp(module_signing, key_usage) == 0)
417 return FALSE;
418 }
419 EXTENDED_KEY_USAGE_free(eku);
420 }
421
422 X509_free(x509);
423 }
424
425 OBJ_cleanup();
426
427 return TRUE;
428}
429
5f0a358b
PJ
430static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
431 UINTN dbsize,
432 WIN_CERTIFICATE_EFI_PKCS *data,
433 UINT8 *hash)
3df68c18 434{
3df68c18 435 EFI_SIGNATURE_DATA *Cert;
b8070380 436 UINTN CertSize;
c13fc2f7 437 BOOLEAN IsFound = FALSE;
53862dda 438 EFI_GUID CertType = X509_GUID;
c16548d0 439
c16548d0 440 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
c13fc2f7 441 if (CompareGuid (&CertList->SignatureType, &CertType) == 0) {
c16548d0 442 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
b8070380
GCPL
443 CertSize = CertList->SignatureSize - sizeof(EFI_GUID);
444 if (verify_x509(Cert->SignatureData, CertSize)) {
62f0afa2
MTL
445 if (verify_eku(Cert->SignatureData, CertSize)) {
446 IsFound = AuthenticodeVerify (data->CertData,
447 data->Hdr.dwLength - sizeof(data->Hdr),
448 Cert->SignatureData,
449 CertSize,
450 hash, SHA256_DIGEST_SIZE);
451 if (IsFound)
452 return DATA_FOUND;
453 }
b8070380
GCPL
454 } else if (verbose) {
455 console_notify(L"Not a DER encoding x.509 Certificate");
c16548d0 456 }
c16548d0
MG
457 }
458
459 dbsize -= CertList->SignatureListSize;
460 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
461 }
462
c16548d0
MG
463 return DATA_NOT_FOUND;
464}
465
5f0a358b
PJ
466static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
467 WIN_CERTIFICATE_EFI_PKCS *data, UINT8 *hash)
c16548d0 468{
5f0a358b 469 CHECK_STATUS rc;
c16548d0 470 EFI_STATUS efi_status;
c16548d0 471 EFI_SIGNATURE_LIST *CertList;
c16548d0 472 UINTN dbsize = 0;
7f0208a0 473 UINT8 *db;
3df68c18 474
7f0208a0 475 efi_status = get_variable(dbname, &db, &dbsize, guid);
3df68c18 476
5f0a358b 477 if (efi_status != EFI_SUCCESS)
c16548d0 478 return VAR_NOT_FOUND;
3df68c18 479
7f0208a0 480 CertList = (EFI_SIGNATURE_LIST *)db;
3df68c18 481
5f0a358b
PJ
482 rc = check_db_cert_in_ram(CertList, dbsize, data, hash);
483
484 FreePool(db);
485
486 return rc;
487}
488
20f6cde6
MG
489/*
490 * Check a hash against an EFI_SIGNATURE_LIST in a buffer
491 */
5f0a358b
PJ
492static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
493 UINTN dbsize, UINT8 *data,
494 int SignatureSize, EFI_GUID CertType)
495{
496 EFI_SIGNATURE_DATA *Cert;
497 UINTN CertCount, Index;
498 BOOLEAN IsFound = FALSE;
499
c16548d0 500 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
d71240bf 501 CertCount = (CertList->SignatureListSize -sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
3df68c18 502 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
c13fc2f7 503 if (CompareGuid(&CertList->SignatureType, &CertType) == 0) {
3df68c18 504 for (Index = 0; Index < CertCount; Index++) {
c16548d0 505 if (CompareMem (Cert->SignatureData, data, SignatureSize) == 0) {
3df68c18
MG
506 //
507 // Find the signature in database.
508 //
509 IsFound = TRUE;
510 break;
511 }
512
513 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
514 }
515 if (IsFound) {
516 break;
517 }
518 }
519
c16548d0 520 dbsize -= CertList->SignatureListSize;
3df68c18
MG
521 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
522 }
523
3df68c18 524 if (IsFound)
c16548d0
MG
525 return DATA_FOUND;
526
527 return DATA_NOT_FOUND;
528}
529
20f6cde6
MG
530/*
531 * Check a hash against an EFI_SIGNATURE_LIST in a UEFI variable
532 */
5f0a358b
PJ
533static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
534 int SignatureSize, EFI_GUID CertType)
535{
536 EFI_STATUS efi_status;
537 EFI_SIGNATURE_LIST *CertList;
5f0a358b 538 UINTN dbsize = 0;
7f0208a0 539 UINT8 *db;
5f0a358b 540
7f0208a0 541 efi_status = get_variable(dbname, &db, &dbsize, guid);
5f0a358b
PJ
542
543 if (efi_status != EFI_SUCCESS) {
544 return VAR_NOT_FOUND;
545 }
546
7f0208a0 547 CertList = (EFI_SIGNATURE_LIST *)db;
5f0a358b
PJ
548
549 CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data,
550 SignatureSize, CertType);
551 FreePool(db);
552 return rc;
553
554}
555
20f6cde6
MG
556/*
557 * Check whether the binary signature or hash are present in dbx or the
558 * built-in blacklist
559 */
ce6a5748
MG
560static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
561 UINT8 *sha256hash, UINT8 *sha1hash)
c16548d0 562{
0a6565c5 563 EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
d3819813 564 EFI_GUID shim_var = SHIM_LOCK_GUID;
92888645 565 EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx;
0a6565c5 566
92888645 567 if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash,
53862dda 568 SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) ==
8b7685b2 569 DATA_FOUND)
5f0a358b 570 return EFI_ACCESS_DENIED;
92888645 571 if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash,
53862dda 572 SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) ==
8b7685b2 573 DATA_FOUND)
5f0a358b 574 return EFI_ACCESS_DENIED;
8044a321
PJ
575 if (cert && check_db_cert_in_ram(dbx, vendor_dbx_size, cert,
576 sha256hash) == DATA_FOUND)
5f0a358b
PJ
577 return EFI_ACCESS_DENIED;
578
0a6565c5 579 if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
53862dda 580 EFI_CERT_SHA256_GUID) == DATA_FOUND)
c16548d0 581 return EFI_ACCESS_DENIED;
0a6565c5 582 if (check_db_hash(L"dbx", secure_var, sha1hash, SHA1_DIGEST_SIZE,
53862dda 583 EFI_CERT_SHA1_GUID) == DATA_FOUND)
ce6a5748 584 return EFI_ACCESS_DENIED;
8044a321
PJ
585 if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash) ==
586 DATA_FOUND)
3df68c18 587 return EFI_ACCESS_DENIED;
d3819813
MTL
588 if (check_db_hash(L"MokListX", shim_var, sha256hash, SHA256_DIGEST_SIZE,
589 EFI_CERT_SHA256_GUID) == DATA_FOUND) {
590 return EFI_ACCESS_DENIED;
591 }
592 if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash) ==
593 DATA_FOUND) {
594 return EFI_ACCESS_DENIED;
595 }
3df68c18
MG
596
597 return EFI_SUCCESS;
598}
599
cbef697a
PJ
600static void update_verification_method(verification_method_t method)
601{
602 if (verification_method == VERIFIED_BY_NOTHING)
603 verification_method = method;
604}
605
20f6cde6
MG
606/*
607 * Check whether the binary signature or hash are present in db or MokList
608 */
ce6a5748
MG
609static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert,
610 UINT8 *sha256hash, UINT8 *sha1hash)
b2058cf8 611{
0a6565c5
MG
612 EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
613 EFI_GUID shim_var = SHIM_LOCK_GUID;
614
47ebeb62
JB
615 if (!ignore_db) {
616 if (check_db_hash(L"db", secure_var, sha256hash, SHA256_DIGEST_SIZE,
617 EFI_CERT_SHA256_GUID) == DATA_FOUND) {
618 update_verification_method(VERIFIED_BY_HASH);
619 return EFI_SUCCESS;
620 }
621 if (check_db_hash(L"db", secure_var, sha1hash, SHA1_DIGEST_SIZE,
622 EFI_CERT_SHA1_GUID) == DATA_FOUND) {
623 verification_method = VERIFIED_BY_HASH;
624 update_verification_method(VERIFIED_BY_HASH);
625 return EFI_SUCCESS;
626 }
8044a321
PJ
627 if (cert && check_db_cert(L"db", secure_var, cert, sha256hash)
628 == DATA_FOUND) {
47ebeb62
JB
629 verification_method = VERIFIED_BY_CERT;
630 update_verification_method(VERIFIED_BY_CERT);
631 return EFI_SUCCESS;
632 }
cbef697a 633 }
47ebeb62 634
0a6565c5 635 if (check_db_hash(L"MokList", shim_var, sha256hash, SHA256_DIGEST_SIZE,
cbef697a
PJ
636 EFI_CERT_SHA256_GUID) == DATA_FOUND) {
637 verification_method = VERIFIED_BY_HASH;
638 update_verification_method(VERIFIED_BY_HASH);
0a6565c5 639 return EFI_SUCCESS;
cbef697a 640 }
8044a321
PJ
641 if (cert && check_db_cert(L"MokList", shim_var, cert, sha256hash) ==
642 DATA_FOUND) {
cbef697a
PJ
643 verification_method = VERIFIED_BY_CERT;
644 update_verification_method(VERIFIED_BY_CERT);
b2058cf8 645 return EFI_SUCCESS;
cbef697a 646 }
b2058cf8 647
cbef697a 648 update_verification_method(VERIFIED_BY_NOTHING);
b2058cf8
MG
649 return EFI_ACCESS_DENIED;
650}
651
6279b58e
MG
652/*
653 * Check whether we're in Secure Boot and user mode
654 */
655
656static BOOLEAN secure_mode (void)
657{
d3819813 658 static int first = 1;
e60f1181 659 if (user_insecure_mode)
9eaadb0d
MG
660 return FALSE;
661
7a72592b 662 if (variable_is_secureboot() != 1) {
d3819813 663 if (verbose && !in_protocol && first)
95c6743e 664 console_notify(L"Secure boot not enabled");
d3819813 665 first = 0;
6b1f8796
PJ
666 return FALSE;
667 }
6279b58e 668
9ea3d9b4
PJ
669 /* If we /do/ have "SecureBoot", but /don't/ have "SetupMode",
670 * then the implementation is bad, but we assume that secure boot is
671 * enabled according to the status of "SecureBoot". If we have both
672 * of them, then "SetupMode" may tell us additional data, and we need
673 * to consider it.
674 */
675 if (variable_is_setupmode(0) == 1) {
d3819813 676 if (verbose && !in_protocol && first)
95c6743e 677 console_notify(L"Platform is in setup mode");
d3819813 678 first = 0;
6279b58e
MG
679 return FALSE;
680 }
681
d3819813 682 first = 0;
6279b58e
MG
683 return TRUE;
684}
685
0dcd5a8e
PJ
686#define check_size_line(data, datasize_in, hashbase, hashsize, l) ({ \
687 if ((unsigned long)hashbase > \
688 (unsigned long)data + datasize_in) { \
689 perror(L"shim.c:%d Invalid hash base 0x%016x\n", l, \
690 hashbase); \
691 goto done; \
692 } \
693 if ((unsigned long)hashbase + hashsize > \
694 (unsigned long)data + datasize_in) { \
695 perror(L"shim.c:%d Invalid hash size 0x%016x\n", l, \
696 hashsize); \
697 goto done; \
698 } \
699})
700#define check_size(d,ds,h,hs) check_size_line(d,ds,h,hs,__LINE__)
701
f898777d 702/*
f394b22e 703 * Calculate the SHA1 and SHA256 hashes of a binary
f898777d 704 */
f394b22e 705
afec82ac 706static EFI_STATUS generate_hash (char *data, unsigned int datasize_in,
f394b22e
MG
707 PE_COFF_LOADER_IMAGE_CONTEXT *context,
708 UINT8 *sha256hash, UINT8 *sha1hash)
709
7f055335 710{
ce6a5748 711 unsigned int sha256ctxsize, sha1ctxsize;
47a9d2c9 712 unsigned int size = datasize_in;
ce6a5748 713 void *sha256ctx = NULL, *sha1ctx = NULL;
7f055335
MG
714 char *hashbase;
715 unsigned int hashsize;
7f055335 716 unsigned int SumOfBytesHashed, SumOfSectionBytes;
3df68c18 717 unsigned int index, pos;
47a9d2c9 718 unsigned int datasize;
7f055335 719 EFI_IMAGE_SECTION_HEADER *Section;
0db1af8a 720 EFI_IMAGE_SECTION_HEADER *SectionHeader = NULL;
f394b22e 721 EFI_STATUS status = EFI_SUCCESS;
16a83563
PJ
722 EFI_IMAGE_DOS_HEADER *DosHdr = (void *)data;
723 unsigned int PEHdr_offset = 0;
7f055335 724
47a9d2c9 725 if (datasize_in < 0) {
e50cfe37 726 perror(L"Invalid data size\n");
47a9d2c9
KC
727 return EFI_INVALID_PARAMETER;
728 }
729 size = datasize = (unsigned int)datasize_in;
730
16a83563
PJ
731 if (datasize <= sizeof (*DosHdr) ||
732 DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
e50cfe37 733 perror(L"Invalid signature\n");
16a83563
PJ
734 return EFI_INVALID_PARAMETER;
735 }
736 PEHdr_offset = DosHdr->e_lfanew;
737
738 sha256ctxsize = Sha256GetContextSize();
739 sha256ctx = AllocatePool(sha256ctxsize);
740
741 sha1ctxsize = Sha1GetContextSize();
742 sha1ctx = AllocatePool(sha1ctxsize);
743
ce6a5748 744 if (!sha256ctx || !sha1ctx) {
e50cfe37 745 perror(L"Unable to allocate memory for hash context\n");
7f055335
MG
746 return EFI_OUT_OF_RESOURCES;
747 }
748
ce6a5748 749 if (!Sha256Init(sha256ctx) || !Sha1Init(sha1ctx)) {
e50cfe37 750 perror(L"Unable to initialise hash\n");
7f055335
MG
751 status = EFI_OUT_OF_RESOURCES;
752 goto done;
753 }
754
755 /* Hash start to checksum */
7db60bd8 756 hashbase = data;
7f055335
MG
757 hashsize = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum -
758 hashbase;
0dcd5a8e 759 check_size(data, datasize_in, hashbase, hashsize);
7f055335 760
ce6a5748
MG
761 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
762 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
e50cfe37 763 perror(L"Unable to generate hash\n");
7f055335
MG
764 status = EFI_OUT_OF_RESOURCES;
765 goto done;
766 }
767
768 /* Hash post-checksum to start of certificate table */
769 hashbase = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum +
770 sizeof (int);
771 hashsize = (char *)context->SecDir - hashbase;
0dcd5a8e 772 check_size(data, datasize_in, hashbase, hashsize);
7f055335 773
ce6a5748
MG
774 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
775 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
e50cfe37 776 perror(L"Unable to generate hash\n");
7f055335
MG
777 status = EFI_OUT_OF_RESOURCES;
778 goto done;
779 }
780
781 /* Hash end of certificate table to end of image header */
afec82ac
PJ
782 EFI_IMAGE_DATA_DIRECTORY *dd = context->SecDir + 1;
783 hashbase = (char *)dd;
784 hashsize = context->SizeOfHeaders - (unsigned long)((char *)dd - data);
785 if (hashsize > datasize_in) {
786 perror(L"Data Directory size %d is invalid\n", hashsize);
787 status = EFI_INVALID_PARAMETER;
788 goto done;
789 }
0dcd5a8e 790 check_size(data, datasize_in, hashbase, hashsize);
0db1af8a 791
ce6a5748
MG
792 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
793 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
e50cfe37 794 perror(L"Unable to generate hash\n");
7f055335
MG
795 status = EFI_OUT_OF_RESOURCES;
796 goto done;
797 }
798
f898777d 799 /* Sort sections */
afec82ac 800 SumOfBytesHashed = context->SizeOfHeaders;
7f055335 801
47a9d2c9 802 /* Validate section locations and sizes */
a63d665f 803 for (index = 0, SumOfSectionBytes = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
47a9d2c9
KC
804 EFI_IMAGE_SECTION_HEADER *SectionPtr;
805
806 /* Validate SectionPtr is within image */
807 SectionPtr = ImageAddress(data, datasize,
16a83563 808 PEHdr_offset +
47a9d2c9
KC
809 sizeof (UINT32) +
810 sizeof (EFI_IMAGE_FILE_HEADER) +
811 context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader +
812 (index * sizeof(*SectionPtr)));
813 if (!SectionPtr) {
e50cfe37 814 perror(L"Malformed section %d\n", index);
47a9d2c9
KC
815 status = EFI_INVALID_PARAMETER;
816 goto done;
817 }
818 /* Validate section size is within image. */
819 if (SectionPtr->SizeOfRawData >
820 datasize - SumOfBytesHashed - SumOfSectionBytes) {
e50cfe37 821 perror(L"Malformed section %d size\n", index);
47a9d2c9
KC
822 status = EFI_INVALID_PARAMETER;
823 goto done;
824 }
825 SumOfSectionBytes += SectionPtr->SizeOfRawData;
7f055335
MG
826 }
827
828 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * context->PEHdr->Pe32.FileHeader.NumberOfSections);
829 if (SectionHeader == NULL) {
e50cfe37 830 perror(L"Unable to allocate section header\n");
7f055335
MG
831 status = EFI_OUT_OF_RESOURCES;
832 goto done;
833 }
834
47a9d2c9 835 /* Already validated above */
16a83563
PJ
836 Section = ImageAddress(data, datasize,
837 PEHdr_offset +
838 sizeof (UINT32) +
47a9d2c9
KC
839 sizeof (EFI_IMAGE_FILE_HEADER) +
840 context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader);
841
7f055335
MG
842 /* Sort the section headers */
843 for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
844 pos = index;
845 while ((pos > 0) && (Section->PointerToRawData < SectionHeader[pos - 1].PointerToRawData)) {
846 CopyMem (&SectionHeader[pos], &SectionHeader[pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
847 pos--;
848 }
849 CopyMem (&SectionHeader[pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
850 Section += 1;
851 }
852
853 /* Hash the sections */
854 for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
855 Section = &SectionHeader[index];
856 if (Section->SizeOfRawData == 0) {
857 continue;
858 }
cf718e19 859 hashbase = ImageAddress(data, size, Section->PointerToRawData);
7f055335 860
f898777d 861 if (!hashbase) {
e50cfe37 862 perror(L"Malformed section header\n");
cbe21407
MG
863 status = EFI_INVALID_PARAMETER;
864 goto done;
f898777d
MG
865 }
866
47a9d2c9
KC
867 /* Verify hashsize within image. */
868 if (Section->SizeOfRawData >
869 datasize - Section->PointerToRawData) {
e50cfe37 870 perror(L"Malformed section raw size %d\n", index);
47a9d2c9
KC
871 status = EFI_INVALID_PARAMETER;
872 goto done;
873 }
874 hashsize = (unsigned int) Section->SizeOfRawData;
0dcd5a8e 875 check_size(data, datasize_in, hashbase, hashsize);
47a9d2c9 876
ce6a5748
MG
877 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
878 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
e50cfe37 879 perror(L"Unable to generate hash\n");
7f055335
MG
880 status = EFI_OUT_OF_RESOURCES;
881 goto done;
882 }
883 SumOfBytesHashed += Section->SizeOfRawData;
884 }
885
886 /* Hash all remaining data */
47a9d2c9 887 if (datasize > SumOfBytesHashed) {
7db60bd8 888 hashbase = data + SumOfBytesHashed;
afec82ac 889 hashsize = datasize - context->SecDir->Size - SumOfBytesHashed;
0dcd5a8e 890 check_size(data, datasize_in, hashbase, hashsize);
7f055335 891
ce6a5748
MG
892 if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
893 !(Sha1Update(sha1ctx, hashbase, hashsize))) {
e50cfe37 894 perror(L"Unable to generate hash\n");
7f055335
MG
895 status = EFI_OUT_OF_RESOURCES;
896 goto done;
897 }
898 }
899
ce6a5748
MG
900 if (!(Sha256Final(sha256ctx, sha256hash)) ||
901 !(Sha1Final(sha1ctx, sha1hash))) {
e50cfe37 902 perror(L"Unable to finalise hash\n");
7f055335
MG
903 status = EFI_OUT_OF_RESOURCES;
904 goto done;
905 }
906
f394b22e
MG
907done:
908 if (SectionHeader)
909 FreePool(SectionHeader);
910 if (sha1ctx)
911 FreePool(sha1ctx);
912 if (sha256ctx)
913 FreePool(sha256ctx);
914
915 return status;
916}
917
20f6cde6
MG
918/*
919 * Ensure that the MOK database hasn't been set or modified from an OS
920 */
0a6565c5
MG
921static EFI_STATUS verify_mok (void) {
922 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
923 EFI_STATUS status = EFI_SUCCESS;
7f0208a0 924 UINT8 *MokListData = NULL;
0a6565c5
MG
925 UINTN MokListDataSize = 0;
926 UINT32 attributes;
927
7f0208a0
GCPL
928 status = get_variable_attr(L"MokList", &MokListData, &MokListDataSize,
929 shim_lock_guid, &attributes);
0a6565c5 930
42426e6e 931 if (!EFI_ERROR(status) && attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
e50cfe37 932 perror(L"MokList is compromised!\nErase all keys in MokList!\n");
0a6565c5 933 if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) {
e50cfe37 934 perror(L"Failed to erase MokList\n");
42426e6e 935 return EFI_ACCESS_DENIED;
0a6565c5 936 }
0a6565c5
MG
937 }
938
ca2e00d0
GCPL
939 if (MokListData)
940 FreePool(MokListData);
941
0a6565c5
MG
942 return EFI_SUCCESS;
943}
944
f394b22e
MG
945/*
946 * Check that the signature is valid and matches the binary
947 */
948static EFI_STATUS verify_buffer (char *data, int datasize,
0a6565c5 949 PE_COFF_LOADER_IMAGE_CONTEXT *context)
f394b22e 950{
f394b22e
MG
951 UINT8 sha256hash[SHA256_DIGEST_SIZE];
952 UINT8 sha1hash[SHA1_DIGEST_SIZE];
953 EFI_STATUS status = EFI_ACCESS_DENIED;
8044a321 954 WIN_CERTIFICATE_EFI_PKCS *cert = NULL;
f394b22e
MG
955 unsigned int size = datasize;
956
8044a321 957 if (context->SecDir->Size != 0) {
62f0afa2
MTL
958 if (context->SecDir->Size >= size) {
959 perror(L"Certificate Database size is too large\n");
960 return EFI_INVALID_PARAMETER;
961 }
962
8044a321
PJ
963 cert = ImageAddress (data, size,
964 context->SecDir->VirtualAddress);
832e5161 965
8044a321 966 if (!cert) {
e50cfe37 967 perror(L"Certificate located outside the image\n");
8044a321
PJ
968 return EFI_INVALID_PARAMETER;
969 }
f394b22e 970
62f0afa2
MTL
971 if (cert->Hdr.dwLength > context->SecDir->Size) {
972 perror(L"Certificate list size is inconsistent with PE headers");
973 return EFI_INVALID_PARAMETER;
974 }
975
8044a321
PJ
976 if (cert->Hdr.wCertificateType !=
977 WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
e50cfe37 978 perror(L"Unsupported certificate type %x\n",
8044a321
PJ
979 cert->Hdr.wCertificateType);
980 return EFI_UNSUPPORTED;
981 }
f394b22e
MG
982 }
983
984 status = generate_hash(data, datasize, context, sha256hash, sha1hash);
f394b22e
MG
985 if (status != EFI_SUCCESS)
986 return status;
987
20f6cde6
MG
988 /*
989 * Check that the MOK database hasn't been modified
990 */
42426e6e
AB
991 status = verify_mok();
992 if (status != EFI_SUCCESS)
993 return status;
0a6565c5 994
20f6cde6
MG
995 /*
996 * Ensure that the binary isn't blacklisted
997 */
ce6a5748 998 status = check_blacklist(cert, sha256hash, sha1hash);
3df68c18
MG
999
1000 if (status != EFI_SUCCESS) {
e50cfe37 1001 perror(L"Binary is blacklisted\n");
f394b22e 1002 return status;
3df68c18
MG
1003 }
1004
20f6cde6
MG
1005 /*
1006 * Check whether the binary is whitelisted in any of the firmware
1007 * databases
1008 */
0a6565c5 1009 status = check_whitelist(cert, sha256hash, sha1hash);
4ab978a3 1010 if (status == EFI_SUCCESS)
0a6565c5 1011 return status;
b2058cf8 1012
8044a321
PJ
1013 if (cert) {
1014 /*
1015 * Check against the shim build key
1016 */
f852734c
GCPL
1017 if (sizeof(shim_cert) &&
1018 AuthenticodeVerify(cert->CertData,
62f0afa2 1019 cert->Hdr.dwLength - sizeof(cert->Hdr),
ef8c9962
MG
1020 shim_cert, sizeof(shim_cert), sha256hash,
1021 SHA256_DIGEST_SIZE)) {
8044a321
PJ
1022 status = EFI_SUCCESS;
1023 return status;
1024 }
ef8c9962 1025
8044a321
PJ
1026 /*
1027 * And finally, check against shim's built-in key
1028 */
62f0afa2
MTL
1029 if (vendor_cert_size &&
1030 AuthenticodeVerify(cert->CertData,
1031 cert->Hdr.dwLength - sizeof(cert->Hdr),
1032 vendor_cert, vendor_cert_size,
1033 sha256hash, SHA256_DIGEST_SIZE)) {
8044a321
PJ
1034 status = EFI_SUCCESS;
1035 return status;
1036 }
13422973
GCPL
1037 }
1038
13422973 1039 status = EFI_ACCESS_DENIED;
7f055335 1040
f898777d
MG
1041 return status;
1042}
b2fe1780 1043
f898777d
MG
1044/*
1045 * Read the binary header and grab appropriate information from it
1046 */
ce78d2d2 1047static EFI_STATUS read_header(void *data, unsigned int datasize,
f898777d
MG
1048 PE_COFF_LOADER_IMAGE_CONTEXT *context)
1049{
7db60bd8
MG
1050 EFI_IMAGE_DOS_HEADER *DosHdr = data;
1051 EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
b6a12d99 1052 unsigned long HeaderWithoutDataDir, SectionHeaderOffset, OptHeaderSize;
62f0afa2 1053 unsigned long FileAlignment = 0;
b2fe1780 1054
afec82ac 1055 if (datasize < sizeof (PEHdr->Pe32)) {
e50cfe37 1056 perror(L"Invalid image\n");
cbe21407
MG
1057 return EFI_UNSUPPORTED;
1058 }
1059
f898777d 1060 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
7db60bd8 1061 PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
afec82ac
PJ
1062
1063 if (!image_is_loadable(PEHdr)) {
1064 perror(L"Platform does not support this image\n");
1065 return EFI_UNSUPPORTED;
1066 }
1067
1068 if (image_is_64_bit(PEHdr)) {
1069 context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
1070 context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
1071 context->ImageSize = PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
d3819813 1072 context->SectionAlignment = PEHdr->Pe32Plus.OptionalHeader.SectionAlignment;
62f0afa2 1073 FileAlignment = PEHdr->Pe32Plus.OptionalHeader.FileAlignment;
afec82ac
PJ
1074 OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);
1075 } else {
1076 context->NumberOfRvaAndSizes = PEHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes;
1077 context->SizeOfHeaders = PEHdr->Pe32.OptionalHeader.SizeOfHeaders;
1078 context->ImageSize = (UINT64)PEHdr->Pe32.OptionalHeader.SizeOfImage;
d3819813 1079 context->SectionAlignment = PEHdr->Pe32.OptionalHeader.SectionAlignment;
62f0afa2 1080 FileAlignment = PEHdr->Pe32.OptionalHeader.FileAlignment;
afec82ac
PJ
1081 OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);
1082 }
1083
62f0afa2
MTL
1084 if (FileAlignment % 2 != 0) {
1085 perror(L"File Alignment is invalid (%d)\n", FileAlignment);
1086 return EFI_UNSUPPORTED;
1087 }
1088 if (FileAlignment == 0)
1089 FileAlignment = 0x200;
1090 if (context->SectionAlignment == 0)
1091 context->SectionAlignment = PAGE_SIZE;
1092 if (context->SectionAlignment < FileAlignment)
1093 context->SectionAlignment = FileAlignment;
1094
b6a12d99 1095 context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections;
b2fe1780 1096
b6a12d99 1097 if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < context->NumberOfRvaAndSizes) {
e50cfe37 1098 perror(L"Image header too small\n");
7de74e67
PJ
1099 return EFI_UNSUPPORTED;
1100 }
1101
b6a12d99 1102 HeaderWithoutDataDir = OptHeaderSize
7de74e67 1103 - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
b6a12d99
M
1104 if (((UINT32)PEHdr->Pe32.FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=
1105 context->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) {
e50cfe37 1106 perror(L"Image header overflows data directory\n");
7de74e67
PJ
1107 return EFI_UNSUPPORTED;
1108 }
1109
1110 SectionHeaderOffset = DosHdr->e_lfanew
1111 + sizeof (UINT32)
1112 + sizeof (EFI_IMAGE_FILE_HEADER)
b6a12d99
M
1113 + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader;
1114 if (((UINT32)context->ImageSize - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
1115 <= context->NumberOfSections) {
e50cfe37 1116 perror(L"Image sections overflow image size\n");
7de74e67
PJ
1117 return EFI_UNSUPPORTED;
1118 }
1119
b6a12d99
M
1120 if ((context->SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
1121 < (UINT32)context->NumberOfSections) {
e50cfe37 1122 perror(L"Image sections overflow section headers\n");
7de74e67
PJ
1123 return EFI_UNSUPPORTED;
1124 }
1125
cbe21407 1126 if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) {
e50cfe37 1127 perror(L"Invalid image\n");
cbe21407
MG
1128 return EFI_UNSUPPORTED;
1129 }
1130
f898777d 1131 if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) {
e50cfe37 1132 perror(L"Unsupported image type\n");
f898777d
MG
1133 return EFI_UNSUPPORTED;
1134 }
b2fe1780 1135
f898777d 1136 if (PEHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) {
e50cfe37 1137 perror(L"Unsupported image - Relocations have been stripped\n");
f898777d
MG
1138 return EFI_UNSUPPORTED;
1139 }
b2fe1780 1140
f898777d 1141 context->PEHdr = PEHdr;
afec82ac
PJ
1142
1143 if (image_is_64_bit(PEHdr)) {
1144 context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
1145 context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint;
1146 context->RelocDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1147 context->SecDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1148 } else {
1149 context->ImageAddress = PEHdr->Pe32.OptionalHeader.ImageBase;
1150 context->EntryPoint = PEHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
1151 context->RelocDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1152 context->SecDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1153 }
1154
b6a12d99 1155 context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
b2fe1780 1156
cbe21407 1157 if (context->ImageSize < context->SizeOfHeaders) {
e50cfe37 1158 perror(L"Invalid image\n");
cbe21407 1159 return EFI_UNSUPPORTED;
b2fe1780
MG
1160 }
1161
47a9d2c9
KC
1162 if ((unsigned long)((UINT8 *)context->SecDir - (UINT8 *)data) >
1163 (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
e50cfe37 1164 perror(L"Invalid image\n");
cbe21407
MG
1165 return EFI_UNSUPPORTED;
1166 }
1167
ce78d2d2 1168 if (context->SecDir->VirtualAddress >= datasize) {
e50cfe37 1169 perror(L"Malformed security header\n");
f898777d
MG
1170 return EFI_INVALID_PARAMETER;
1171 }
f898777d 1172 return EFI_SUCCESS;
b2fe1780
MG
1173}
1174
f898777d
MG
1175/*
1176 * Once the image has been loaded it needs to be validated and relocated
1177 */
000c565c
GCPL
1178static EFI_STATUS handle_image (void *data, unsigned int datasize,
1179 EFI_LOADED_IMAGE *li)
b2fe1780
MG
1180{
1181 EFI_STATUS efi_status;
1182 char *buffer;
47a9d2c9 1183 int i;
b2fe1780 1184 EFI_IMAGE_SECTION_HEADER *Section;
0e6b0195 1185 char *base, *end;
b2fe1780 1186 PE_COFF_LOADER_IMAGE_CONTEXT context;
d3819813
MTL
1187 unsigned int alignment;
1188 int found_entry_point = 0;
7f055335 1189
20f6cde6
MG
1190 /*
1191 * The binary header contains relevant context and section pointers
1192 */
ce78d2d2 1193 efi_status = read_header(data, datasize, &context);
b2fe1780 1194 if (efi_status != EFI_SUCCESS) {
e50cfe37 1195 perror(L"Failed to read header: %r\n", efi_status);
b2fe1780
MG
1196 return efi_status;
1197 }
1198
20f6cde6
MG
1199 /*
1200 * We only need to verify the binary if we're in secure mode
1201 */
6279b58e 1202 if (secure_mode ()) {
0a6565c5 1203 efi_status = verify_buffer(data, datasize, &context);
7f055335 1204
4ab978a3
PJ
1205 if (EFI_ERROR(efi_status)) {
1206 console_error(L"Verification failed", efi_status);
6279b58e 1207 return efi_status;
4ab978a3
PJ
1208 } else {
1209 if (verbose)
1210 console_notify(L"Verification succeeded");
6279b58e 1211 }
7f055335
MG
1212 }
1213
d3819813
MTL
1214 /* The spec says, uselessly, of SectionAlignment:
1215 * =====
1216 * The alignment (in bytes) of sections when they are loaded into
1217 * memory. It must be greater than or equal to FileAlignment. The
1218 * default is the page size for the architecture.
1219 * =====
1220 * Which doesn't tell you whose responsibility it is to enforce the
1221 * "default", or when. It implies that the value in the field must
1222 * be > FileAlignment (also poorly defined), but it appears visual
1223 * studio will happily write 512 for FileAlignment (its default) and
1224 * 0 for SectionAlignment, intending to imply PAGE_SIZE.
1225 *
1226 * We only support one page size, so if it's zero, nerf it to 4096.
1227 */
1228 alignment = context.SectionAlignment;
1229 if (!alignment)
1230 alignment = 4096;
1231
1232 buffer = AllocatePool(context.ImageSize + context.SectionAlignment);
1233 buffer = ALIGN_POINTER(buffer, alignment);
b2fe1780 1234
0e6b0195 1235 if (!buffer) {
e50cfe37 1236 perror(L"Failed to allocate image buffer\n");
0e6b0195
MG
1237 return EFI_OUT_OF_RESOURCES;
1238 }
1239
7db60bd8 1240 CopyMem(buffer, data, context.SizeOfHeaders);
b2fe1780 1241
d3819813
MTL
1242 entry_point = ImageAddress(buffer, context.ImageSize, context.EntryPoint);
1243 if (!entry_point) {
1244 perror(L"Entry point is invalid\n");
1245 FreePool(buffer);
1246 return EFI_UNSUPPORTED;
1247 }
1248
1249
a16340e3 1250 char *RelocBase, *RelocBaseEnd;
d3819813
MTL
1251 /*
1252 * These are relative virtual addresses, so we have to check them
1253 * against the image size, not the data size.
1254 */
1255 RelocBase = ImageAddress(buffer, context.ImageSize,
a16340e3 1256 context.RelocDir->VirtualAddress);
d3819813
MTL
1257 /*
1258 * RelocBaseEnd here is the address of the last byte of the table
1259 */
1260 RelocBaseEnd = ImageAddress(buffer, context.ImageSize,
a16340e3
PJ
1261 context.RelocDir->VirtualAddress +
1262 context.RelocDir->Size - 1);
1263
1264 EFI_IMAGE_SECTION_HEADER *RelocSection = NULL;
1265
20f6cde6
MG
1266 /*
1267 * Copy the executable's sections to their desired offsets
1268 */
b2fe1780 1269 Section = context.FirstSection;
4ca60879 1270 for (i = 0; i < context.NumberOfSections; i++, Section++) {
d3819813
MTL
1271 base = ImageAddress (buffer, context.ImageSize,
1272 Section->VirtualAddress);
1273 end = ImageAddress (buffer, context.ImageSize,
1274 Section->VirtualAddress
1275 + Section->Misc.VirtualSize - 1);
1276
1277 if (end < base) {
1278 perror(L"Section %d has negative size\n", i);
1279 FreePool(buffer);
b2fe1780 1280 return EFI_UNSUPPORTED;
7de74e67
PJ
1281 }
1282
d3819813
MTL
1283 if (Section->VirtualAddress <= context.EntryPoint &&
1284 (Section->VirtualAddress + Section->SizeOfRawData - 1)
1285 > context.EntryPoint)
1286 found_entry_point++;
b2fe1780 1287
a16340e3
PJ
1288 /* We do want to process .reloc, but it's often marked
1289 * discardable, so we don't want to memcpy it. */
1290 if (CompareMem(Section->Name, ".reloc\0\0", 8) == 0) {
1291 if (RelocSection) {
1292 perror(L"Image has multiple relocation sections\n");
1293 return EFI_UNSUPPORTED;
1294 }
1295 /* If it has nonzero sizes, and our bounds check
1296 * made sense, and the VA and size match RelocDir's
1297 * versions, then we believe in this section table. */
1298 if (Section->SizeOfRawData &&
1299 Section->Misc.VirtualSize &&
1300 base && end &&
1301 RelocBase == base &&
1302 RelocBaseEnd == end) {
1303 RelocSection = Section;
1304 }
1305 }
1306
d3819813 1307 if (Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) {
a16340e3
PJ
1308 continue;
1309 }
1310
d3819813
MTL
1311 if (!base) {
1312 perror(L"Section %d has invalid base address\n", i);
1313 return EFI_UNSUPPORTED;
1314 }
1315 if (!end) {
1316 perror(L"Section %d has zero size\n", i);
1317 return EFI_UNSUPPORTED;
1318 }
1319
1320 if (!(Section->Characteristics & EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA) &&
1321 (Section->VirtualAddress < context.SizeOfHeaders ||
1322 Section->PointerToRawData < context.SizeOfHeaders)) {
1323 perror(L"Section %d is inside image headers\n", i);
1324 return EFI_UNSUPPORTED;
1325 }
1326
62f0afa2
MTL
1327 if (Section->Characteristics & EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
1328 ZeroMem(base, Section->Misc.VirtualSize);
1329 } else {
1330 if (Section->PointerToRawData < context.SizeOfHeaders) {
1331 perror(L"Section %d is inside image headers\n", i);
1332 return EFI_UNSUPPORTED;
1333 }
1334
1335 if (Section->SizeOfRawData > 0)
1336 CopyMem(base, data + Section->PointerToRawData,
1337 Section->SizeOfRawData);
b2fe1780 1338
62f0afa2
MTL
1339 if (Section->SizeOfRawData < Section->Misc.VirtualSize)
1340 ZeroMem(base + Section->SizeOfRawData,
1341 Section->Misc.VirtualSize - Section->SizeOfRawData);
1342 }
b2fe1780
MG
1343 }
1344
486bf03e
PJ
1345 if (context.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
1346 perror(L"Image has no relocation entry\n");
0db1af8a 1347 FreePool(buffer);
486bf03e
PJ
1348 return EFI_UNSUPPORTED;
1349 }
1350
a16340e3 1351 if (context.RelocDir->Size && RelocSection) {
486bf03e
PJ
1352 /*
1353 * Run the relocation fixups
1354 */
a16340e3
PJ
1355 efi_status = relocate_coff(&context, RelocSection, data,
1356 buffer);
486bf03e
PJ
1357
1358 if (efi_status != EFI_SUCCESS) {
1359 perror(L"Relocation failed: %r\n", efi_status);
1360 FreePool(buffer);
1361 return efi_status;
1362 }
b2fe1780
MG
1363 }
1364
20f6cde6
MG
1365 /*
1366 * grub needs to know its location and size in memory, so fix up
1367 * the loaded image protocol values
1368 */
5fe882ba
MG
1369 li->ImageBase = buffer;
1370 li->ImageSize = context.ImageSize;
1371
09e2c939
GCPL
1372 /* Pass the load options to the second stage loader */
1373 li->LoadOptions = load_options;
1374 li->LoadOptionsSize = load_options_size;
1375
d3819813
MTL
1376 if (!found_entry_point) {
1377 perror(L"Entry point is not within sections\n");
1378 return EFI_UNSUPPORTED;
1379 }
1380 if (found_entry_point > 1) {
1381 perror(L"%d sections contain entry point\n");
0e6b0195
MG
1382 return EFI_UNSUPPORTED;
1383 }
b2fe1780
MG
1384
1385 return EFI_SUCCESS;
1386}
1387
6d6b0221
PJ
1388static int
1389should_use_fallback(EFI_HANDLE image_handle)
1390{
1391 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
1392 EFI_LOADED_IMAGE *li;
6d6b0221 1393 unsigned int pathlen = 0;
fe8527aa 1394 CHAR16 *bootpath = NULL;
6d6b0221 1395 EFI_FILE_IO_INTERFACE *fio = NULL;
d3819813
MTL
1396 EFI_FILE *vh = NULL;
1397 EFI_FILE *fh = NULL;
6d6b0221 1398 EFI_STATUS rc;
fe8527aa 1399 int ret = 0;
6d6b0221
PJ
1400
1401 rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
1402 &loaded_image_protocol, (void **)&li);
c9d11306 1403 if (EFI_ERROR(rc)) {
e50cfe37 1404 perror(L"Could not get image for bootx64.efi: %r\n", rc);
6d6b0221 1405 return 0;
c9d11306 1406 }
6d6b0221 1407
2e7fc28d 1408 bootpath = DevicePathToStr(li->FilePath);
6d6b0221
PJ
1409
1410 /* Check the beginning of the string and the end, to avoid
1411 * caring about which arch this is. */
1412 /* I really don't know why, but sometimes bootpath gives us
1413 * L"\\EFI\\BOOT\\/BOOTX64.EFI". So just handle that here...
1414 */
1415 if (StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\BOOT", 14) &&
d3819813
MTL
1416 StrnCaseCmp(bootpath, L"\\EFI\\BOOT\\/BOOT", 15) &&
1417 StrnCaseCmp(bootpath, L"EFI\\BOOT\\BOOT", 13) &&
1418 StrnCaseCmp(bootpath, L"EFI\\BOOT\\/BOOT", 14))
fe8527aa 1419 goto error;
2e7fc28d 1420
6d6b0221
PJ
1421 pathlen = StrLen(bootpath);
1422 if (pathlen < 5 || StrCaseCmp(bootpath + pathlen - 4, L".EFI"))
fe8527aa 1423 goto error;
6d6b0221 1424
6d6b0221 1425 rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle,
35b0b55b 1426 &FileSystemProtocol, (void **)&fio);
c9d11306 1427 if (EFI_ERROR(rc)) {
e50cfe37 1428 perror(L"Could not get fio for li->DeviceHandle: %r\n", rc);
fe8527aa 1429 goto error;
c9d11306 1430 }
e50cfe37 1431
6d6b0221 1432 rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh);
c9d11306 1433 if (EFI_ERROR(rc)) {
e50cfe37 1434 perror(L"Could not open fio volume: %r\n", rc);
fe8527aa 1435 goto error;
c9d11306 1436 }
6d6b0221
PJ
1437
1438 rc = uefi_call_wrapper(vh->Open, 5, vh, &fh, L"\\EFI\\BOOT" FALLBACK,
5bb3e64e 1439 EFI_FILE_MODE_READ, 0);
6d6b0221 1440 if (EFI_ERROR(rc)) {
b32a3ce1
PJ
1441 /* Do not print the error here - this is an acceptable case
1442 * for removable media, where we genuinely don't want
1443 * fallback.efi to exist.
1444 * Print(L"Could not open \"\\EFI\\BOOT%s\": %d\n", FALLBACK,
1445 * rc);
1446 */
fe8527aa 1447 goto error;
6d6b0221 1448 }
6d6b0221 1449
fe8527aa
GCPL
1450 ret = 1;
1451error:
d3819813
MTL
1452 if (fh)
1453 uefi_call_wrapper(fh->Close, 1, fh);
1454 if (vh)
1455 uefi_call_wrapper(vh->Close, 1, vh);
fe8527aa
GCPL
1456 if (bootpath)
1457 FreePool(bootpath);
1458
1459 return ret;
6d6b0221
PJ
1460}
1461
20f6cde6
MG
1462/*
1463 * Generate the path of an executable given shim's path and the name
1464 * of the executable
1465 */
822d089e 1466static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath,
c9022560 1467 CHAR16 **PathName)
f898777d 1468{
0db1af8a 1469 EFI_DEVICE_PATH *devpath;
47a9d2c9
KC
1470 unsigned int i;
1471 int j, last = -1;
db54b0a4
MG
1472 unsigned int pathlen = 0;
1473 EFI_STATUS efi_status = EFI_SUCCESS;
bc6aaefa 1474 CHAR16 *bootpath;
f898777d 1475
d3819813
MTL
1476 /*
1477 * Suuuuper lazy technique here, but check and see if this is a full
1478 * path to something on the ESP. Backwards compatibility demands
1479 * that we don't just use \\, becuase we (not particularly brightly)
1480 * used to require that the relative file path started with that.
1481 *
1482 * If it is a full path, don't try to merge it with the directory
1483 * from our Loaded Image handle.
1484 */
1485 if (StrSize(ImagePath) > 5 && StrnCmp(ImagePath, L"\\EFI\\", 5) == 0) {
1486 *PathName = StrDuplicate(ImagePath);
1487 if (!*PathName) {
1488 perror(L"Failed to allocate path buffer\n");
1489 return EFI_OUT_OF_RESOURCES;
1490 }
1491 return EFI_SUCCESS;
1492 }
1493
0db1af8a 1494 devpath = li->FilePath;
f898777d 1495
bc6aaefa 1496 bootpath = DevicePathToStr(devpath);
f898777d 1497
bc6aaefa 1498 pathlen = StrLen(bootpath);
f898777d 1499
f9f81a22
GCPL
1500 /*
1501 * DevicePathToStr() concatenates two nodes with '/'.
1502 * Convert '/' to '\\'.
1503 */
1504 for (i = 0; i < pathlen; i++) {
1505 if (bootpath[i] == '/')
1506 bootpath[i] = '\\';
1507 }
436afcc2 1508
bc6aaefa 1509 for (i=pathlen; i>0; i--) {
436afcc2
GCPL
1510 if (bootpath[i] == '\\' && bootpath[i-1] == '\\')
1511 bootpath[i] = '/';
1512 else if (last == -1 && bootpath[i] == '\\')
1513 last = i;
1514 }
1515
1516 if (last == -1 && bootpath[0] == '\\')
1517 last = 0;
1518 bootpath[last+1] = '\0';
1519
1520 if (last > 0) {
1521 for (i = 0, j = 0; bootpath[i] != '\0'; i++) {
1522 if (bootpath[i] != '/') {
1523 bootpath[j] = bootpath[i];
1524 j++;
1525 }
1526 }
1527 bootpath[j] = '\0';
f898777d
MG
1528 }
1529
f9f81a22
GCPL
1530 while (*ImagePath == '\\')
1531 ImagePath++;
00ced0c1 1532
822d089e 1533 *PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath));
f898777d 1534
db54b0a4 1535 if (!*PathName) {
e50cfe37 1536 perror(L"Failed to allocate path buffer\n");
0db1af8a
MG
1537 efi_status = EFI_OUT_OF_RESOURCES;
1538 goto error;
f898777d
MG
1539 }
1540
bc6aaefa 1541 *PathName[0] = '\0';
155a76bb
PJ
1542 if (StrnCaseCmp(bootpath, ImagePath, StrLen(bootpath)))
1543 StrCat(*PathName, bootpath);
822d089e 1544 StrCat(*PathName, ImagePath);
db54b0a4 1545
db54b0a4 1546error:
f9f81a22
GCPL
1547 FreePool(bootpath);
1548
db54b0a4
MG
1549 return efi_status;
1550}
1551
1552/*
20f6cde6 1553 * Open the second stage bootloader and read it into a buffer
db54b0a4 1554 */
822d089e
GCPL
1555static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data,
1556 int *datasize, CHAR16 *PathName)
db54b0a4
MG
1557{
1558 EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
1559 EFI_GUID file_info_id = EFI_FILE_INFO_ID;
1560 EFI_STATUS efi_status;
1561 EFI_HANDLE device;
1562 EFI_FILE_INFO *fileinfo = NULL;
1563 EFI_FILE_IO_INTERFACE *drive;
1564 EFI_FILE *root, *grub;
6eb1eca4 1565 UINTN buffersize = sizeof(EFI_FILE_INFO);
db54b0a4
MG
1566
1567 device = li->DeviceHandle;
f898777d 1568
20f6cde6
MG
1569 /*
1570 * Open the device
1571 */
0db1af8a 1572 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
ed711b02
MG
1573 &simple_file_system_protocol,
1574 (void **)&drive);
f898777d 1575
0db1af8a 1576 if (efi_status != EFI_SUCCESS) {
e50cfe37 1577 perror(L"Failed to find fs: %r\n", efi_status);
0db1af8a
MG
1578 goto error;
1579 }
f898777d 1580
0db1af8a
MG
1581 efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
1582
1583 if (efi_status != EFI_SUCCESS) {
e50cfe37 1584 perror(L"Failed to open fs: %r\n", efi_status);
0db1af8a
MG
1585 goto error;
1586 }
f898777d 1587
20f6cde6
MG
1588 /*
1589 * And then open the file
1590 */
f898777d
MG
1591 efi_status = uefi_call_wrapper(root->Open, 5, root, &grub, PathName,
1592 EFI_FILE_MODE_READ, 0);
1593
1594 if (efi_status != EFI_SUCCESS) {
e50cfe37 1595 perror(L"Failed to open %s - %r\n", PathName, efi_status);
0db1af8a
MG
1596 goto error;
1597 }
1598
1599 fileinfo = AllocatePool(buffersize);
1600
1601 if (!fileinfo) {
e50cfe37 1602 perror(L"Unable to allocate file info buffer\n");
0db1af8a
MG
1603 efi_status = EFI_OUT_OF_RESOURCES;
1604 goto error;
f898777d
MG
1605 }
1606
20f6cde6
MG
1607 /*
1608 * Find out how big the file is in order to allocate the storage
1609 * buffer
1610 */
f898777d
MG
1611 efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub, &file_info_id,
1612 &buffersize, fileinfo);
1613
1614 if (efi_status == EFI_BUFFER_TOO_SMALL) {
cbe21407 1615 FreePool(fileinfo);
f898777d
MG
1616 fileinfo = AllocatePool(buffersize);
1617 if (!fileinfo) {
e50cfe37 1618 perror(L"Unable to allocate file info buffer\n");
0db1af8a
MG
1619 efi_status = EFI_OUT_OF_RESOURCES;
1620 goto error;
f898777d
MG
1621 }
1622 efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub,
1623 &file_info_id, &buffersize,
1624 fileinfo);
1625 }
1626
1627 if (efi_status != EFI_SUCCESS) {
e50cfe37 1628 perror(L"Unable to get file info: %r\n", efi_status);
0db1af8a 1629 goto error;
f898777d
MG
1630 }
1631
1632 buffersize = fileinfo->FileSize;
0db1af8a 1633
7db60bd8 1634 *data = AllocatePool(buffersize);
f898777d 1635
7db60bd8 1636 if (!*data) {
e50cfe37 1637 perror(L"Unable to allocate file buffer\n");
0db1af8a
MG
1638 efi_status = EFI_OUT_OF_RESOURCES;
1639 goto error;
f898777d 1640 }
20f6cde6
MG
1641
1642 /*
1643 * Perform the actual read
1644 */
f898777d 1645 efi_status = uefi_call_wrapper(grub->Read, 3, grub, &buffersize,
7db60bd8 1646 *data);
f898777d 1647
0db1af8a
MG
1648 if (efi_status == EFI_BUFFER_TOO_SMALL) {
1649 FreePool(*data);
1650 *data = AllocatePool(buffersize);
1651 efi_status = uefi_call_wrapper(grub->Read, 3, grub,
1652 &buffersize, *data);
f898777d
MG
1653 }
1654
1655 if (efi_status != EFI_SUCCESS) {
e50cfe37 1656 perror(L"Unexpected return from initial read: %r, buffersize %x\n", efi_status, buffersize);
0db1af8a 1657 goto error;
f898777d
MG
1658 }
1659
7db60bd8 1660 *datasize = buffersize;
f898777d 1661
cbe21407
MG
1662 FreePool(fileinfo);
1663
f898777d 1664 return EFI_SUCCESS;
0db1af8a
MG
1665error:
1666 if (*data) {
1667 FreePool(*data);
1668 *data = NULL;
1669 }
6f161626 1670
0db1af8a
MG
1671 if (fileinfo)
1672 FreePool(fileinfo);
1673 return efi_status;
f898777d
MG
1674}
1675
20f6cde6
MG
1676/*
1677 * Protocol entry point. If secure boot is enabled, verify that the provided
1678 * buffer is signed with a trusted key.
1679 */
db54b0a4 1680EFI_STATUS shim_verify (void *buffer, UINT32 size)
f4b24734 1681{
d3819813 1682 EFI_STATUS status = EFI_SUCCESS;
f4b24734
MG
1683 PE_COFF_LOADER_IMAGE_CONTEXT context;
1684
cbef697a 1685 loader_is_participating = 1;
e50cfe37 1686 in_protocol = 1;
cbef697a 1687
6279b58e 1688 if (!secure_mode())
d3819813 1689 goto done;
6279b58e 1690
ce78d2d2 1691 status = read_header(buffer, size, &context);
f4b24734 1692 if (status != EFI_SUCCESS)
e50cfe37 1693 goto done;
f4b24734 1694
0a6565c5 1695 status = verify_buffer(buffer, size, &context);
e50cfe37
GCPL
1696done:
1697 in_protocol = 0;
1698 return status;
1699}
1700
1701static EFI_STATUS shim_hash (char *data, int datasize,
1702 PE_COFF_LOADER_IMAGE_CONTEXT *context,
1703 UINT8 *sha256hash, UINT8 *sha1hash)
1704{
1705 EFI_STATUS status;
1706
1707 in_protocol = 1;
1708 status = generate_hash(data, datasize, context, sha256hash, sha1hash);
1709 in_protocol = 0;
1710
1711 return status;
1712}
1713
1714static EFI_STATUS shim_read_header(void *data, unsigned int datasize,
1715 PE_COFF_LOADER_IMAGE_CONTEXT *context)
1716{
1717 EFI_STATUS status;
1718
1719 in_protocol = 1;
1720 status = read_header(data, datasize, context);
1721 in_protocol = 0;
f4b24734
MG
1722
1723 return status;
1724}
1725
20f6cde6
MG
1726/*
1727 * Load and run an EFI executable
1728 */
cec6a0a9 1729EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
822d089e 1730{
cec6a0a9 1731 EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
822d089e 1732 EFI_STATUS efi_status;
cec6a0a9 1733 EFI_LOADED_IMAGE *li, li_bak;
1c595706
MG
1734 CHAR16 *PathName = NULL;
1735 void *sourcebuffer = NULL;
fbc486b5 1736 UINT64 sourcesize = 0;
822d089e
GCPL
1737 void *data = NULL;
1738 int datasize;
1739
20f6cde6
MG
1740 /*
1741 * We need to refer to the loaded image protocol on the running
1742 * binary in order to find our path
1743 */
cec6a0a9 1744 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
ed711b02 1745 &loaded_image_protocol, (void **)&li);
cec6a0a9
GCPL
1746
1747 if (efi_status != EFI_SUCCESS) {
e50cfe37 1748 perror(L"Unable to init protocol\n");
cec6a0a9
GCPL
1749 return efi_status;
1750 }
1751
20f6cde6
MG
1752 /*
1753 * Build a new path from the existing one plus the executable name
1754 */
c9022560 1755 efi_status = generate_path(li, ImagePath, &PathName);
cec6a0a9
GCPL
1756
1757 if (efi_status != EFI_SUCCESS) {
e50cfe37 1758 perror(L"Unable to generate path %s: %r\n", ImagePath, efi_status);
cec6a0a9
GCPL
1759 goto done;
1760 }
1761
da49ac6d 1762 if (findNetboot(li->DeviceHandle)) {
1c595706
MG
1763 efi_status = parseNetbootinfo(image_handle);
1764 if (efi_status != EFI_SUCCESS) {
e50cfe37 1765 perror(L"Netboot parsing failed: %r\n", efi_status);
1c595706
MG
1766 return EFI_PROTOCOL_ERROR;
1767 }
1768 efi_status = FetchNetbootimage(image_handle, &sourcebuffer,
1769 &sourcesize);
1770 if (efi_status != EFI_SUCCESS) {
e50cfe37 1771 perror(L"Unable to fetch TFTP image: %r\n", efi_status);
1c595706
MG
1772 return efi_status;
1773 }
1774 data = sourcebuffer;
1775 datasize = sourcesize;
62f0afa2
MTL
1776#if defined(ENABLE_HTTPBOOT)
1777 } else if (find_httpboot(li->DeviceHandle)) {
1778 efi_status = httpboot_fetch_buffer (image_handle, &sourcebuffer,
1779 &sourcesize);
1780 if (efi_status != EFI_SUCCESS) {
1781 perror(L"Unable to fetch HTTP image: %r\n", efi_status);
1782 return efi_status;
1783 }
1784 data = sourcebuffer;
1785 datasize = sourcesize;
1786#endif
1c595706 1787 } else {
4ad234f1
MG
1788 /*
1789 * Read the new executable off disk
1790 */
1c595706 1791 efi_status = load_image(li, &data, &datasize, PathName);
822d089e 1792
1c595706 1793 if (efi_status != EFI_SUCCESS) {
e50cfe37 1794 perror(L"Failed to load image %s: %r\n", PathName, efi_status);
1c595706
MG
1795 goto done;
1796 }
822d089e
GCPL
1797 }
1798
d3819813
MTL
1799 /* Measure the binary into the TPM */
1800 tpm_log_event((EFI_PHYSICAL_ADDRESS)data, datasize, 9,
1801 (CHAR8 *)"Second stage bootloader");
1802
20f6cde6
MG
1803 /*
1804 * We need to modify the loaded image protocol entry before running
1805 * the new binary, so back it up
1806 */
822d089e
GCPL
1807 CopyMem(&li_bak, li, sizeof(li_bak));
1808
20f6cde6
MG
1809 /*
1810 * Verify and, if appropriate, relocate and execute the executable
1811 */
822d089e
GCPL
1812 efi_status = handle_image(data, datasize, li);
1813
1814 if (efi_status != EFI_SUCCESS) {
e50cfe37 1815 perror(L"Failed to load image: %r\n", efi_status);
822d089e
GCPL
1816 CopyMem(li, &li_bak, sizeof(li_bak));
1817 goto done;
1818 }
1819
cbef697a
PJ
1820 loader_is_participating = 0;
1821
20f6cde6
MG
1822 /*
1823 * The binary is trusted and relocated. Run it
1824 */
cbe21407 1825 efi_status = uefi_call_wrapper(entry_point, 2, image_handle, systab);
822d089e 1826
20f6cde6
MG
1827 /*
1828 * Restore our original loaded image values
1829 */
822d089e
GCPL
1830 CopyMem(li, &li_bak, sizeof(li_bak));
1831done:
cbe21407
MG
1832 if (PathName)
1833 FreePool(PathName);
1834
1835 if (data)
1836 FreePool(data);
1837
822d089e
GCPL
1838 return efi_status;
1839}
1840
20f6cde6
MG
1841/*
1842 * Load and run grub. If that fails because grub isn't trusted, load and
1843 * run MokManager.
1844 */
db54b0a4 1845EFI_STATUS init_grub(EFI_HANDLE image_handle)
b2fe1780
MG
1846{
1847 EFI_STATUS efi_status;
d3819813 1848 int use_fb = should_use_fallback(image_handle);
f4b24734 1849
d3819813 1850 efi_status = start_image(image_handle, use_fb ? FALLBACK :second_stage);
b2fe1780 1851
d3819813 1852 if (efi_status == EFI_SECURITY_VIOLATION) {
ef8c9962 1853 efi_status = start_image(image_handle, MOK_MANAGER);
d3819813
MTL
1854 if (efi_status != EFI_SUCCESS) {
1855 Print(L"start_image() returned %r\n", efi_status);
1856 uefi_call_wrapper(BS->Stall, 1, 2000000);
1857 return efi_status;
1858 }
1859
1860 efi_status = start_image(image_handle,
1861 use_fb ? FALLBACK : second_stage);
1862 }
1863
1864 if (efi_status != EFI_SUCCESS) {
1865 Print(L"start_image() returned %r\n", efi_status);
1866 uefi_call_wrapper(BS->Stall, 1, 2000000);
1867 }
1868
1869 return efi_status;
1870}
1871
1872/*
1873 * Measure some of the MOK variables into the TPM
1874 */
1875EFI_STATUS measure_mok()
1876{
1877 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1878 EFI_STATUS efi_status;
1879 UINT8 *Data = NULL;
1880 UINTN DataSize = 0;
1881
1882 efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid);
1883 if (efi_status != EFI_SUCCESS)
1884 return efi_status;
1885
1886 efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)Data, DataSize, 14,
1887 (CHAR8 *)"MokList");
1888
1889 FreePool(Data);
1890
1891 if (efi_status != EFI_SUCCESS)
1892 return efi_status;
1893
1894 efi_status = get_variable(L"MokSBState", &Data, &DataSize,
1895 shim_lock_guid);
1896
1897 if (efi_status != EFI_SUCCESS)
1898 return efi_status;
1899
1900 efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)Data, DataSize, 14,
1901 (CHAR8 *)"MokSBState");
1902
1903 FreePool(Data);
db54b0a4
MG
1904
1905 return efi_status;
1906}
1907
20f6cde6
MG
1908/*
1909 * Copy the boot-services only MokList variable to the runtime-accessible
1910 * MokListRT variable. It's not marked NV, so the OS can't modify it.
1911 */
a903fb10
GCPL
1912EFI_STATUS mirror_mok_list()
1913{
1914 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1915 EFI_STATUS efi_status;
7f0208a0 1916 UINT8 *Data = NULL;
a903fb10 1917 UINTN DataSize = 0;
4185c7d6
PJ
1918 void *FullData = NULL;
1919 UINTN FullDataSize = 0;
1920 EFI_SIGNATURE_LIST *CertList = NULL;
1921 EFI_SIGNATURE_DATA *CertData = NULL;
1922 uint8_t *p = NULL;
a903fb10 1923
7f0208a0 1924 efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid);
4185c7d6
PJ
1925 if (efi_status != EFI_SUCCESS)
1926 DataSize = 0;
1927
ada75ade
PJ
1928 if (vendor_cert_size) {
1929 FullDataSize = DataSize
1930 + sizeof (*CertList)
1931 + sizeof (EFI_GUID)
1932 + vendor_cert_size
1933 ;
1934 FullData = AllocatePool(FullDataSize);
1935 if (!FullData) {
1936 perror(L"Failed to allocate space for MokListRT\n");
1937 return EFI_OUT_OF_RESOURCES;
1938 }
1939 p = FullData;
a903fb10 1940
ada75ade
PJ
1941 if (efi_status == EFI_SUCCESS && DataSize > 0) {
1942 CopyMem(p, Data, DataSize);
1943 p += DataSize;
1944 }
1945 CertList = (EFI_SIGNATURE_LIST *)p;
1946 p += sizeof (*CertList);
1947 CertData = (EFI_SIGNATURE_DATA *)p;
1948 p += sizeof (EFI_GUID);
1949
1950 CertList->SignatureType = EFI_CERT_X509_GUID;
1951 CertList->SignatureListSize = vendor_cert_size
1952 + sizeof (*CertList)
1953 + sizeof (*CertData)
1954 -1;
1955 CertList->SignatureHeaderSize = 0;
1956 CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID);
1957
1958 CertData->SignatureOwner = SHIM_LOCK_GUID;
1959 CopyMem(p, vendor_cert, vendor_cert_size);
1960 } else {
1961 FullDataSize = DataSize;
1962 FullData = Data;
a903fb10
GCPL
1963 }
1964
1965 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListRT",
1966 &shim_lock_guid,
1967 EFI_VARIABLE_BOOTSERVICE_ACCESS
1968 | EFI_VARIABLE_RUNTIME_ACCESS,
4185c7d6 1969 FullDataSize, FullData);
a903fb10 1970 if (efi_status != EFI_SUCCESS) {
e50cfe37 1971 perror(L"Failed to set MokListRT: %r\n", efi_status);
a903fb10
GCPL
1972 }
1973
a903fb10
GCPL
1974 return efi_status;
1975}
1976
d3819813
MTL
1977/*
1978 * Copy the boot-services only MokListX variable to the runtime-accessible
1979 * MokListXRT variable. It's not marked NV, so the OS can't modify it.
1980 */
1981EFI_STATUS mirror_mok_list_x()
1982{
1983 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1984 EFI_STATUS efi_status;
1985 UINT8 *Data = NULL;
1986 UINTN DataSize = 0;
1987
1988 efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid);
1989 if (efi_status != EFI_SUCCESS)
1990 return efi_status;
1991
1992 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListXRT",
1993 &shim_lock_guid,
1994 EFI_VARIABLE_BOOTSERVICE_ACCESS
1995 | EFI_VARIABLE_RUNTIME_ACCESS,
1996 DataSize, Data);
1997 if (efi_status != EFI_SUCCESS) {
1998 console_error(L"Failed to set MokListRT", efi_status);
1999 }
2000
2001 return efi_status;
2002}
2003
2004/*
2005 * Copy the boot-services only MokSBState variable to the runtime-accessible
2006 * MokSBStateRT variable. It's not marked NV, so the OS can't modify it.
2007 */
2008EFI_STATUS mirror_mok_sb_state()
2009{
2010 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2011 EFI_STATUS efi_status;
2012 UINT8 *Data = NULL;
2013 UINTN DataSize = 0;
2014
2015 efi_status = get_variable(L"MokSBState", &Data, &DataSize, shim_lock_guid);
2016 if (efi_status != EFI_SUCCESS)
2017 return efi_status;
2018
2019 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokSBStateRT",
2020 &shim_lock_guid,
2021 EFI_VARIABLE_BOOTSERVICE_ACCESS
2022 | EFI_VARIABLE_RUNTIME_ACCESS,
2023 DataSize, Data);
2024 if (efi_status != EFI_SUCCESS) {
2025 console_error(L"Failed to set MokSBStateRT", efi_status);
2026 }
2027
2028 return efi_status;
2029}
2030
20f6cde6
MG
2031/*
2032 * Check if a variable exists
2033 */
d5a2d9ea 2034static BOOLEAN check_var(CHAR16 *varname)
4b34567d
GCPL
2035{
2036 EFI_STATUS efi_status;
e470969e 2037 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1041805a 2038 UINTN size = sizeof(UINT32);
801d1b93 2039 UINT32 MokVar;
e470969e
GCPL
2040 UINT32 attributes;
2041
d5a2d9ea 2042 efi_status = uefi_call_wrapper(RT->GetVariable, 5, varname,
1041805a 2043 &shim_lock_guid, &attributes,
d5a2d9ea 2044 &size, (void *)&MokVar);
e470969e 2045
d5a2d9ea
MG
2046 if (efi_status == EFI_SUCCESS || efi_status == EFI_BUFFER_TOO_SMALL)
2047 return TRUE;
4b34567d 2048
d5a2d9ea
MG
2049 return FALSE;
2050}
4b34567d 2051
20f6cde6
MG
2052/*
2053 * If the OS has set any of these variables we need to drop into MOK and
2054 * handle them appropriately
2055 */
d5a2d9ea
MG
2056EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
2057{
2058 EFI_STATUS efi_status;
4b34567d 2059
d5a2d9ea 2060 if (check_var(L"MokNew") || check_var(L"MokSB") ||
92a136d8 2061 check_var(L"MokPW") || check_var(L"MokAuth") ||
d3819813
MTL
2062 check_var(L"MokDel") || check_var(L"MokDB") ||
2063 check_var(L"MokXNew") || check_var(L"MokXDel") ||
2064 check_var(L"MokXAuth")) {
9272bc5b 2065 efi_status = start_image(image_handle, MOK_MANAGER);
4b34567d 2066
9272bc5b 2067 if (efi_status != EFI_SUCCESS) {
e50cfe37 2068 perror(L"Failed to start MokManager: %r\n", efi_status);
9272bc5b
MG
2069 return efi_status;
2070 }
4b34567d 2071 }
4b34567d 2072
9272bc5b 2073 return EFI_SUCCESS;
4b34567d
GCPL
2074}
2075
20f6cde6
MG
2076/*
2077 * Verify that MokSBState is valid, and if appropriate set insecure mode
2078 */
9eaadb0d
MG
2079static EFI_STATUS check_mok_sb (void)
2080{
2081 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2082 EFI_STATUS status = EFI_SUCCESS;
875eb1b9
GCPL
2083 UINT8 MokSBState;
2084 UINTN MokSBStateSize = sizeof(MokSBState);
9eaadb0d
MG
2085 UINT32 attributes;
2086
e60f1181 2087 user_insecure_mode = 0;
0948ac09
PJ
2088 ignore_db = 0;
2089
875eb1b9
GCPL
2090 status = uefi_call_wrapper(RT->GetVariable, 5, L"MokSBState", &shim_lock_guid,
2091 &attributes, &MokSBStateSize, &MokSBState);
9eaadb0d
MG
2092 if (status != EFI_SUCCESS)
2093 return EFI_ACCESS_DENIED;
2094
20f6cde6
MG
2095 /*
2096 * Delete and ignore the variable if it's been set from or could be
2097 * modified by the OS
2098 */
9eaadb0d 2099 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
e50cfe37 2100 perror(L"MokSBState is compromised! Clearing it\n");
9eaadb0d 2101 if (LibDeleteVariable(L"MokSBState", &shim_lock_guid) != EFI_SUCCESS) {
e50cfe37 2102 perror(L"Failed to erase MokSBState\n");
9eaadb0d
MG
2103 }
2104 status = EFI_ACCESS_DENIED;
2105 } else {
875eb1b9 2106 if (MokSBState == 1) {
e60f1181 2107 user_insecure_mode = 1;
9eaadb0d
MG
2108 }
2109 }
2110
2111 return status;
4b34567d
GCPL
2112}
2113
47ebeb62
JB
2114/*
2115 * Verify that MokDBState is valid, and if appropriate set ignore db mode
2116 */
2117
2118static EFI_STATUS check_mok_db (void)
2119{
2120 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2121 EFI_STATUS status = EFI_SUCCESS;
875eb1b9 2122 UINT8 MokDBState;
62f0afa2 2123 UINTN MokDBStateSize = sizeof(MokDBState);
47ebeb62
JB
2124 UINT32 attributes;
2125
875eb1b9
GCPL
2126 status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDBState", &shim_lock_guid,
2127 &attributes, &MokDBStateSize, &MokDBState);
47ebeb62
JB
2128 if (status != EFI_SUCCESS)
2129 return EFI_ACCESS_DENIED;
2130
2131 ignore_db = 0;
2132
2133 /*
2134 * Delete and ignore the variable if it's been set from or could be
2135 * modified by the OS
2136 */
2137 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
e50cfe37 2138 perror(L"MokDBState is compromised! Clearing it\n");
47ebeb62 2139 if (LibDeleteVariable(L"MokDBState", &shim_lock_guid) != EFI_SUCCESS) {
e50cfe37 2140 perror(L"Failed to erase MokDBState\n");
47ebeb62
JB
2141 }
2142 status = EFI_ACCESS_DENIED;
2143 } else {
875eb1b9 2144 if (MokDBState == 1) {
47ebeb62
JB
2145 ignore_db = 1;
2146 }
2147 }
2148
47ebeb62
JB
2149 return status;
2150}
2151
2152static EFI_STATUS mok_ignore_db()
2153{
2154 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2155 EFI_STATUS efi_status = EFI_SUCCESS;
2156 UINT8 Data = 1;
2157 UINTN DataSize = sizeof(UINT8);
2158
2159 check_mok_db();
2160
2161 if (ignore_db) {
2162 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokIgnoreDB",
2163 &shim_lock_guid,
2164 EFI_VARIABLE_BOOTSERVICE_ACCESS
2165 | EFI_VARIABLE_RUNTIME_ACCESS,
2166 DataSize, (void *)&Data);
2167 if (efi_status != EFI_SUCCESS) {
e50cfe37 2168 perror(L"Failed to set MokIgnoreDB: %r\n", efi_status);
47ebeb62
JB
2169 }
2170 }
2171
2172 return efi_status;
2173
2174}
2175
d3819813
MTL
2176EFI_GUID bds_guid = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } };
2177
2178static inline EFI_STATUS
2179get_load_option_optional_data(UINT8 *data, UINTN data_size,
2180 UINT8 **od, UINTN *ods)
2181{
2182 /*
2183 * If it's not at least Attributes + FilePathListLength +
2184 * Description=L"" + 0x7fff0400 (EndEntrireDevicePath), it can't
2185 * be valid.
2186 */
2187 if (data_size < (sizeof(UINT32) + sizeof(UINT16) + 2 + 4))
2188 return EFI_INVALID_PARAMETER;
2189
2190 UINT8 *cur = data + sizeof(UINT32);
2191 UINT16 fplistlen = *(UINT16 *)cur;
2192 /*
2193 * If there's not enough space for the file path list and the
2194 * smallest possible description (L""), it's not valid.
2195 */
2196 if (fplistlen > data_size - (sizeof(UINT32) + 2 + 4))
2197 return EFI_INVALID_PARAMETER;
2198
2199 cur += sizeof(UINT16);
2200 UINTN limit = data_size - (cur - data) - fplistlen;
2201 UINTN i;
2202 for (i = 0; i < limit ; i++) {
2203 /* If the description isn't valid UCS2-LE, it's not valid. */
2204 if (i % 2 != 0) {
2205 if (cur[i] != 0)
2206 return EFI_INVALID_PARAMETER;
2207 } else if (cur[i] == 0) {
2208 /* we've found the end */
2209 i++;
2210 if (i >= limit || cur[i] != 0)
2211 return EFI_INVALID_PARAMETER;
2212 break;
2213 }
2214 }
2215 i++;
2216 if (i > limit)
2217 return EFI_INVALID_PARAMETER;
2218
2219 /*
2220 * If i is limit, we know the rest of this is the FilePathList and
2221 * there's no optional data. So just bail now.
2222 */
2223 if (i == limit) {
2224 *od = NULL;
2225 *ods = 0;
2226 return EFI_SUCCESS;
2227 }
2228
2229 cur += i;
2230 limit -= i;
2231 limit += fplistlen;
2232 i = 0;
2233 while (limit - i >= 4) {
2234 struct {
2235 UINT8 type;
2236 UINT8 subtype;
2237 UINT16 len;
2238 } dp = {
2239 .type = cur[i],
2240 .subtype = cur[i+1],
2241 /*
2242 * it's a little endian UINT16, but we're not
2243 * guaranteed alignment is sane, so we can't just
2244 * typecast it directly.
2245 */
2246 .len = (cur[i+3] << 8) | cur[i+2],
2247 };
2248
2249 /*
2250 * We haven't found an EndEntire, so this has to be a valid
2251 * EFI_DEVICE_PATH in order for the data to be valid. That
2252 * means it has to fit, and it can't be smaller than 4 bytes.
2253 */
2254 if (dp.len < 4 || dp.len > limit)
2255 return EFI_INVALID_PARAMETER;
2256
2257 /*
2258 * see if this is an EndEntire node...
2259 */
2260 if (dp.type == 0x7f && dp.subtype == 0xff) {
2261 /*
2262 * if we've found the EndEntire node, it must be 4
2263 * bytes
2264 */
2265 if (dp.len != 4)
2266 return EFI_INVALID_PARAMETER;
2267
2268 i += dp.len;
2269 break;
2270 }
2271
2272 /*
2273 * It's just some random DP node; skip it.
2274 */
2275 i += dp.len;
2276 }
2277 if (i != fplistlen)
2278 return EFI_INVALID_PARAMETER;
2279
2280 /*
2281 * if there's any space left, it's "optional data"
2282 */
2283 *od = cur + i;
2284 *ods = limit - i;
2285 return EFI_SUCCESS;
2286}
2287
09e2c939
GCPL
2288/*
2289 * Check the load options to specify the second stage loader
2290 */
2291EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
2292{
2293 EFI_STATUS status;
2294 EFI_LOADED_IMAGE *li;
d3819813 2295 CHAR16 *start = NULL;
47a9d2c9 2296 int remaining_size = 0;
0283024e 2297 CHAR16 *loader_str = NULL;
d3819813
MTL
2298 UINTN loader_len = 0;
2299 unsigned int i;
09e2c939
GCPL
2300
2301 second_stage = DEFAULT_LOADER;
2302 load_options = NULL;
2303 load_options_size = 0;
2304
2305 status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
2306 &LoadedImageProtocol, (void **) &li);
2307 if (status != EFI_SUCCESS) {
e50cfe37 2308 perror (L"Failed to get load options: %r\n", status);
09e2c939
GCPL
2309 return status;
2310 }
2311
d3819813
MTL
2312 /* So, load options are a giant pain in the ass. If we're invoked
2313 * from the EFI shell, we get something like this:
2314
231500000000 5c 00 45 00 36 00 49 00 5c 00 66 00 65 00 64 00 |\.E.F.I.\.f.e.d.|
231600000010 6f 00 72 00 61 00 5c 00 73 00 68 00 69 00 6d 00 |o.r.a.\.s.h.i.m.|
231700000020 78 00 36 00 34 00 2e 00 64 00 66 00 69 00 20 00 |x.6.4...e.f.i. .|
231800000030 5c 00 45 00 46 00 49 00 5c 00 66 00 65 00 64 00 |\.E.F.I.\.f.e.d.|
231900000040 6f 00 72 00 61 00 5c 00 66 00 77 00 75 00 70 00 |o.r.a.\.f.w.u.p.|
232000000050 64 00 61 00 74 00 65 00 2e 00 65 00 66 00 20 00 |d.a.t.e.e.f.i. .|
232100000060 00 00 66 00 73 00 30 00 3a 00 5c 00 00 00 |..f.s.0.:.\...|
2322
2323 *
2324 * which is just some paths rammed together separated by a UCS-2 NUL.
2325 * But if we're invoked from BDS, we get something more like:
2326 *
2327
232800000000 01 00 00 00 62 00 4c 00 69 00 6e 00 75 00 78 00 |....b.L.i.n.u.x.|
232900000010 20 00 46 00 69 00 72 00 6d 00 77 00 61 00 72 00 | .F.i.r.m.w.a.r.|
233000000020 65 00 20 00 55 00 70 00 64 00 61 00 74 00 65 00 |e. .U.p.d.a.t.e.|
233100000030 72 00 00 00 40 01 2a 00 01 00 00 00 00 08 00 00 |r.....*.........|
233200000040 00 00 00 00 00 40 06 00 00 00 00 00 1a 9e 55 bf |.....@........U.|
233300000050 04 57 f2 4f b4 4a ed 26 4a 40 6a 94 02 02 04 04 |.W.O.:.&J@j.....|
233400000060 34 00 5c 00 45 00 46 00 49 00 5c 00 66 00 65 00 |4.\.E.F.I.f.e.d.|
233500000070 64 00 6f 00 72 00 61 00 5c 00 73 00 68 00 69 00 |o.r.a.\.s.h.i.m.|
233600000080 6d 00 78 00 36 00 34 00 2e 00 65 00 66 00 69 00 |x.6.4...e.f.i...|
233700000090 00 00 7f ff 40 00 20 00 5c 00 66 00 77 00 75 00 |...... .\.f.w.u.|
2338000000a0 70 00 78 00 36 00 34 00 2e 00 65 00 66 00 69 00 |p.x.6.4...e.f.i.|
2339000000b0 00 00 |..|
2340
2341 *
2342 * which is clearly an EFI_LOAD_OPTION filled in halfway reasonably.
2343 * In short, the UEFI shell is still a useless piece of junk.
2344 *
2345 * But then on some versions of BDS, we get:
2346
234700000000 5c 00 66 00 77 00 75 00 70 00 78 00 36 00 34 00 |\.f.w.u.p.x.6.4.|
234800000010 2e 00 65 00 66 00 69 00 00 00 |..e.f.i...|
23490000001a
2350
2351 * which as you can see is one perfectly normal UCS2-EL string
2352 * containing the load option from the Boot#### variable.
2353 *
2354 * We also sometimes find a guid or partial guid at the end, because
2355 * BDS will add that, but we ignore that here.
2356 */
2357
2358 /*
2359 * In either case, we've got to have at least a UCS2 NUL...
2360 */
2361 if (li->LoadOptionsSize < 2)
09e2c939 2362 return EFI_BAD_BUFFER_SIZE;
d3819813
MTL
2363
2364 /*
2365 * Some awesome versions of BDS will add entries for Linux. On top
2366 * of that, some versions of BDS will "tag" any Boot#### entries they
2367 * create by putting a GUID at the very end of the optional data in
2368 * the EFI_LOAD_OPTIONS, thus screwing things up for everybody who
2369 * tries to actually *use* the optional data for anything. Why they
2370 * did this instead of adding a flag to the spec to /say/ it's
2371 * created by BDS, I do not know. For shame.
2372 *
2373 * Anyway, just nerf that out from the start. It's always just
2374 * garbage at the end.
2375 */
2376 if (li->LoadOptionsSize > 16) {
2377 if (CompareGuid((EFI_GUID *)(li->LoadOptions
2378 + (li->LoadOptionsSize - 16)),
2379 &bds_guid) == 0)
2380 li->LoadOptionsSize -= 16;
09e2c939
GCPL
2381 }
2382
0283024e 2383 /*
d3819813
MTL
2384 * Check and see if this is just a list of strings. If it's an
2385 * EFI_LOAD_OPTION, it'll be 0, since we know EndEntire device path
2386 * won't pass muster as UCS2-LE.
2387 *
2388 * If there are 3 strings, we're launched from the shell most likely,
2389 * But we actually only care about the second one.
0283024e 2390 */
d3819813
MTL
2391 UINTN strings = count_ucs2_strings(li->LoadOptions,
2392 li->LoadOptionsSize);
2393 /*
2394 * If it's not string data, try it as an EFI_LOAD_OPTION.
2395 */
2396 if (strings == 0) {
2397 /*
2398 * We at least didn't find /enough/ strings. See if it works
2399 * as an EFI_LOAD_OPTION.
2400 */
2401 status = get_load_option_optional_data(li->LoadOptions,
2402 li->LoadOptionsSize,
2403 (UINT8 **)&start,
2404 &loader_len);
2405 if (status != EFI_SUCCESS)
2406 return EFI_SUCCESS;
2407
2408 remaining_size = 0;
2409 } else if (strings >= 2) {
2410 /*
2411 * UEFI shell copies the whole line of the command into
2412 * LoadOptions. We ignore the string before the first L' ',
2413 * i.e. the name of this program.
2414 * Counting by two bytes is safe, because we know the size is
2415 * compatible with a UCS2-LE string.
2416 */
2417 UINT8 *cur = li->LoadOptions;
2418 for (i = 0; i < li->LoadOptionsSize - 2; i += 2) {
2419 CHAR16 c = (cur[i+1] << 8) | cur[i];
2420 if (c == L' ') {
2421 start = (CHAR16 *)&cur[i+2];
2422 remaining_size = li->LoadOptionsSize - i - 2;
2423 break;
2424 }
09e2c939 2425 }
09e2c939 2426
d3819813
MTL
2427 if (!start || remaining_size <= 0 || start[0] == L'\0')
2428 return EFI_SUCCESS;
6e1bd3dc 2429
d3819813
MTL
2430 for (i = 0; start[i] != '\0'; i++) {
2431 if (start[i] == L' ')
2432 start[i] = L'\0';
2433 if (start[i] == L'\0') {
2434 loader_len = 2 * i + 2;
2435 break;
2436 }
2437 }
2438 if (loader_len)
2439 remaining_size -= loader_len;
2440 } else {
2441 /* only find one string */
2442 start = li->LoadOptions;
2443 loader_len = li->LoadOptionsSize;
0283024e
GCPL
2444 }
2445
2446 /*
d3819813
MTL
2447 * Just to be sure all that math is right...
2448 */
2449 if (loader_len % 2 != 0)
2450 return EFI_INVALID_PARAMETER;
2451
2452 strings = count_ucs2_strings((UINT8 *)start, loader_len);
2453 if (strings < 1)
2454 return EFI_SUCCESS;
2455
2456 /*
2457 * Set up the name of the alternative loader and the LoadOptions for
0283024e
GCPL
2458 * the loader
2459 */
2460 if (loader_len > 0) {
d3819813 2461 loader_str = AllocatePool(loader_len);
0283024e 2462 if (!loader_str) {
e50cfe37 2463 perror(L"Failed to allocate loader string\n");
0283024e
GCPL
2464 return EFI_OUT_OF_RESOURCES;
2465 }
d3819813
MTL
2466
2467 for (i = 0; i < loader_len / 2; i++)
0283024e 2468 loader_str[i] = start[i];
d3819813 2469 loader_str[loader_len/2-1] = L'\0';
0283024e
GCPL
2470
2471 second_stage = loader_str;
d3819813 2472 load_options = remaining_size ? start + loader_len : NULL;
09e2c939
GCPL
2473 load_options_size = remaining_size;
2474 }
2475
2476 return EFI_SUCCESS;
2477}
2478
cf90edff
PJ
2479static SHIM_LOCK shim_lock_interface;
2480static EFI_HANDLE shim_lock_handle;
2481
2482EFI_STATUS
2483install_shim_protocols(void)
2484{
2485 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
2486 EFI_STATUS efi_status;
d3819813
MTL
2487
2488 if (!secure_mode())
2489 return EFI_SUCCESS;
2490
cf90edff
PJ
2491 /*
2492 * Install the protocol
2493 */
2494 efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4,
2495 &shim_lock_handle, &shim_lock_guid,
2496 EFI_NATIVE_INTERFACE, &shim_lock_interface);
2497 if (EFI_ERROR(efi_status)) {
2498 console_error(L"Could not install security protocol",
2499 efi_status);
2500 return efi_status;
2501 }
2502
2503#if defined(OVERRIDE_SECURITY_POLICY)
2504 /*
2505 * Install the security protocol hook
2506 */
2507 security_policy_install(shim_verify);
2508#endif
2509
2510 return EFI_SUCCESS;
2511}
2512
2513void
2514uninstall_shim_protocols(void)
db54b0a4
MG
2515{
2516 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
d3819813
MTL
2517
2518 if (!secure_mode())
2519 return;
2520
cf90edff
PJ
2521#if defined(OVERRIDE_SECURITY_POLICY)
2522 /*
2523 * Clean up the security protocol hook
2524 */
2525 security_policy_uninstall();
2526#endif
2527
2528 /*
2529 * If we're back here then clean everything up before exiting
2530 */
2531 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, shim_lock_handle,
2532 &shim_lock_guid, &shim_lock_interface);
2533}
2534
d3819813
MTL
2535EFI_STATUS
2536shim_init(void)
2537{
2538 EFI_STATUS status = EFI_SUCCESS;
2539 setup_console(1);
2540 setup_verbosity();
2541 dprinta(shim_version);
2542
2543 /* Set the second stage loader */
2544 set_second_stage (image_handle);
2545
2546 if (secure_mode()) {
2547 if (vendor_cert_size || vendor_dbx_size) {
2548 /*
2549 * If shim includes its own certificates then ensure
2550 * that anything it boots has performed some
2551 * validation of the next image.
2552 */
2553 hook_system_services(systab);
2554 loader_is_participating = 0;
2555 }
2556
2557 hook_exit(systab);
2558
2559 status = install_shim_protocols();
2560 }
2561 return status;
2562}
2563
2564void
2565shim_fini(void)
2566{
2567 if (secure_mode()) {
2568 /*
2569 * Remove our protocols
2570 */
2571 uninstall_shim_protocols();
2572
2573 /*
2574 * Remove our hooks from system services.
2575 */
2576 unhook_system_services();
2577 unhook_exit();
2578 }
2579
2580 /*
2581 * Free the space allocated for the alternative 2nd stage loader
2582 */
2583 if (load_options_size > 0 && second_stage)
2584 FreePool(second_stage);
2585
2586 setup_console(0);
2587}
2588
2589extern EFI_STATUS
2590efi_main(EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab);
2591
2592static void
2593__attribute__((__optimize__("0")))
2594debug_hook(void)
2595{
2596 EFI_GUID guid = SHIM_LOCK_GUID;
2597 UINT8 *data = NULL;
2598 UINTN dataSize = 0;
2599 EFI_STATUS efi_status;
2600 volatile register UINTN x = 0;
2601 extern char _text, _data;
2602
2603 if (x)
2604 return;
2605
2606 efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, guid);
2607 if (EFI_ERROR(efi_status)) {
2608 return;
2609 }
2610
2611 Print(L"add-symbol-file "DEBUGDIR
62f0afa2 2612 L"shim" EFI_ARCH L".efi.debug 0x%08x -s .data 0x%08x\n", &_text,
d3819813
MTL
2613 &_data);
2614
2615 Print(L"Pausing for debugger attachment.\n");
2616 Print(L"To disable this, remove the EFI variable SHIM_DEBUG-%g .\n",
2617 &guid);
2618 x = 1;
2619 while (x++) {
2620 /* Make this so it can't /totally/ DoS us. */
2621#if defined(__x86_64__) || defined(__i386__) || defined(__i686__)
2622 if (x > 4294967294ULL)
2623 break;
2624 __asm__ __volatile__("pause");
2625#elif defined(__aarch64__)
2626 if (x > 1000)
2627 break;
2628 __asm__ __volatile__("wfi");
2629#else
2630 if (x > 12000)
2631 break;
2632 uefi_call_wrapper(BS->Stall, 1, 5000);
2633#endif
2634 }
2635 x = 1;
2636}
2637
2638EFI_STATUS
2639efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
cf90edff 2640{
0a232ca9 2641 EFI_STATUS efi_status;
db54b0a4 2642
cbef697a
PJ
2643 verification_method = VERIFIED_BY_NOTHING;
2644
a1f28635
PJ
2645 vendor_cert_size = cert_table.vendor_cert_size;
2646 vendor_dbx_size = cert_table.vendor_dbx_size;
2647 vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset;
2648 vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset;
2649
20f6cde6
MG
2650 /*
2651 * Set up the shim lock protocol so that grub and MokManager can
2652 * call back in and use shim functions
2653 */
db54b0a4 2654 shim_lock_interface.Verify = shim_verify;
e50cfe37
GCPL
2655 shim_lock_interface.Hash = shim_hash;
2656 shim_lock_interface.Context = shim_read_header;
db54b0a4
MG
2657
2658 systab = passed_systab;
d3819813 2659 image_handle = passed_image_handle;
db54b0a4 2660
20f6cde6
MG
2661 /*
2662 * Ensure that gnu-efi functions are available
2663 */
db54b0a4
MG
2664 InitializeLib(image_handle, systab);
2665
d3819813
MTL
2666 /*
2667 * if SHIM_DEBUG is set, wait for a debugger to attach.
2668 */
2669 debug_hook();
0fb089ee 2670
d3819813
MTL
2671 /*
2672 * Measure the MOK variables
2673 */
2674 efi_status = measure_mok();
2675 if (efi_status != EFI_SUCCESS && efi_status != EFI_NOT_FOUND) {
2676 Print(L"Something has gone seriously wrong: %r\n", efi_status);
2677 Print(L"Shim was unable to measure state into the TPM\n");
2678 systab->BootServices->Stall(5000000);
2679 systab->RuntimeServices->ResetSystem(EfiResetShutdown,
2680 EFI_SECURITY_VIOLATION,
2681 0, NULL);
2682 }
09e2c939 2683
20f6cde6
MG
2684 /*
2685 * Check whether the user has configured the system to run in
2686 * insecure mode
2687 */
9eaadb0d
MG
2688 check_mok_sb();
2689
d3819813
MTL
2690 efi_status = shim_init();
2691 if (EFI_ERROR(efi_status)) {
2692 Print(L"Something has gone seriously wrong: %r\n", efi_status);
2693 Print(L"shim cannot continue, sorry.\n");
2694 uefi_call_wrapper(BS->Stall, 1, 5000000);
2695 uefi_call_wrapper(systab->RuntimeServices->ResetSystem, 4,
2696 EfiResetShutdown, EFI_SECURITY_VIOLATION,
2697 0, NULL);
2698 }
2699
20f6cde6
MG
2700 /*
2701 * Tell the user that we're in insecure mode if necessary
2702 */
e60f1181 2703 if (user_insecure_mode) {
9eaadb0d
MG
2704 Print(L"Booting in insecure mode\n");
2705 uefi_call_wrapper(BS->Stall, 1, 2000000);
2706 }
2707
20f6cde6
MG
2708 /*
2709 * Enter MokManager if necessary
2710 */
4b34567d
GCPL
2711 efi_status = check_mok_request(image_handle);
2712
20f6cde6 2713 /*
d3819813
MTL
2714 * Copy the MOK list to a runtime variable so the kernel can
2715 * make use of it
20f6cde6 2716 */
a903fb10
GCPL
2717 efi_status = mirror_mok_list();
2718
d3819813 2719 efi_status = mirror_mok_list_x();
47ebeb62 2720
20f6cde6 2721 /*
d3819813
MTL
2722 * Copy the MOK SB State to a runtime variable so the kernel can
2723 * make use of it
20f6cde6 2724 */
d3819813 2725 efi_status = mirror_mok_sb_state();
db54b0a4 2726
59dcd9d1 2727 /*
d3819813
MTL
2728 * Create the runtime MokIgnoreDB variable so the kernel can
2729 * make use of it
59dcd9d1 2730 */
d3819813 2731 efi_status = mok_ignore_db();
59dcd9d1 2732
0283024e 2733 /*
d3819813 2734 * Hand over control to the second stage bootloader
0283024e 2735 */
d3819813 2736 efi_status = init_grub(image_handle);
bc71a15e 2737
d3819813 2738 shim_fini();
0a232ca9 2739 return efi_status;
b2fe1780 2740}