diff options
Diffstat (limited to 'shim.c')
-rw-r--r-- | shim.c | 324 |
1 files changed, 252 insertions, 72 deletions
@@ -33,28 +33,22 @@ * Corporation. */ -#include <efi.h> -#include <efilib.h> -#include <Library/BaseCryptLib.h> -#include "PeImage.h" #include "shim.h" -#include "netboot.h" -#include "httpboot.h" -#include "shim_cert.h" -#include "replacements.h" -#include "tpm.h" -#include "ucs2.h" - -#include "guid.h" -#include "variables.h" -#include "efiauthenticated.h" -#include "security_policy.h" -#include "console.h" -#include "version.h" - -#include <stdarg.h> + +#include <openssl/err.h> +#include <openssl/bn.h> +#include <openssl/dh.h> +#include <openssl/ocsp.h> +#include <openssl/pkcs12.h> +#include <openssl/rand.h> +#include <openssl/crypto.h> +#include <openssl/ssl.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include <openssl/rsa.h> +#include <openssl/dso.h> + +#include <Library/BaseCryptLib.h> #define FALLBACK L"\\fb" EFI_ARCH L".efi" #define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" @@ -74,6 +68,7 @@ static UINT8 in_protocol; UINTN __perror_ret = 0; \ if (!in_protocol) \ __perror_ret = Print((fmt), ##__VA_ARGS__); \ + LogError(fmt, ##__VA_ARGS__); \ __perror_ret; \ }) @@ -371,6 +366,14 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, return EFI_SUCCESS; } +static void +drain_openssl_errors(void) +{ + unsigned long err = -1; + while (err != 0) + err = ERR_get_error(); +} + static BOOLEAN verify_x509(UINT8 *Cert, UINTN CertSize) { UINTN length; @@ -422,13 +425,16 @@ static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize) X509_free(x509); } + OBJ_cleanup(); + return TRUE; } static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, UINTN dbsize, WIN_CERTIFICATE_EFI_PKCS *data, - UINT8 *hash) + UINT8 *hash, CHAR16 *dbname, + EFI_GUID guid) { EFI_SIGNATURE_DATA *Cert; UINTN CertSize; @@ -446,8 +452,13 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, Cert->SignatureData, CertSize, hash, SHA256_DIGEST_SIZE); - if (IsFound) + if (IsFound) { + tpm_measure_variable(dbname, guid, CertSize, Cert->SignatureData); return DATA_FOUND; + drain_openssl_errors(); + } else { + LogError(L"AuthenticodeVerify(): %d\n", IsFound); + } } } else if (verbose) { console_notify(L"Not a DER encoding x.509 Certificate"); @@ -471,13 +482,12 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid, UINT8 *db; efi_status = get_variable(dbname, &db, &dbsize, guid); - if (efi_status != EFI_SUCCESS) return VAR_NOT_FOUND; CertList = (EFI_SIGNATURE_LIST *)db; - rc = check_db_cert_in_ram(CertList, dbsize, data, hash); + rc = check_db_cert_in_ram(CertList, dbsize, data, hash, dbname, guid); FreePool(db); @@ -489,7 +499,8 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid, */ static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList, UINTN dbsize, UINT8 *data, - int SignatureSize, EFI_GUID CertType) + int SignatureSize, EFI_GUID CertType, + CHAR16 *dbname, EFI_GUID guid) { EFI_SIGNATURE_DATA *Cert; UINTN CertCount, Index; @@ -505,6 +516,7 @@ static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList, // Find the signature in database. // IsFound = TRUE; + tpm_measure_variable(dbname, guid, SignatureSize, data); break; } @@ -545,7 +557,8 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data, CertList = (EFI_SIGNATURE_LIST *)db; CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data, - SignatureSize, CertType); + SignatureSize, CertType, + dbname, guid); FreePool(db); return rc; @@ -563,35 +576,52 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx; if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash, - SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) == - DATA_FOUND) + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID, + L"dbx", secure_var) == + DATA_FOUND) { + LogError(L"binary sha256hash found in vendor dbx\n"); return EFI_SECURITY_VIOLATION; + } if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash, - SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) == - DATA_FOUND) + SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID, + L"dbx", secure_var) == + DATA_FOUND) { + LogError(L"binary sha1hash found in vendor dbx\n"); return EFI_SECURITY_VIOLATION; + } if (cert && check_db_cert_in_ram(dbx, vendor_dbx_size, cert, - sha256hash) == DATA_FOUND) + sha256hash, L"dbx", + secure_var) == DATA_FOUND) { + LogError(L"cert sha256hash found in vendor dbx\n"); return EFI_SECURITY_VIOLATION; - + } if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE, - EFI_CERT_SHA256_GUID) == DATA_FOUND) + EFI_CERT_SHA256_GUID) == DATA_FOUND) { + LogError(L"binary sha256hash found in system dbx\n"); return EFI_SECURITY_VIOLATION; + } if (check_db_hash(L"dbx", secure_var, sha1hash, SHA1_DIGEST_SIZE, - EFI_CERT_SHA1_GUID) == DATA_FOUND) + EFI_CERT_SHA1_GUID) == DATA_FOUND) { + LogError(L"binary sha1hash found in system dbx\n"); return EFI_SECURITY_VIOLATION; + } if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash) == - DATA_FOUND) + DATA_FOUND) { + LogError(L"cert sha256hash found in system dbx\n"); return EFI_SECURITY_VIOLATION; + } if (check_db_hash(L"MokListX", shim_var, sha256hash, SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) == DATA_FOUND) { + LogError(L"binary sha256hash found in Mok dbx\n"); return EFI_SECURITY_VIOLATION; } if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash) == DATA_FOUND) { + LogError(L"cert sha256hash found in Mok dbx\n"); return EFI_SECURITY_VIOLATION; } + drain_openssl_errors(); return EFI_SUCCESS; } @@ -615,18 +645,24 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, EFI_CERT_SHA256_GUID) == DATA_FOUND) { update_verification_method(VERIFIED_BY_HASH); return EFI_SUCCESS; + } else { + LogError(L"check_db_hash(db, sha256hash) != DATA_FOUND\n"); } if (check_db_hash(L"db", secure_var, sha1hash, SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) == DATA_FOUND) { verification_method = VERIFIED_BY_HASH; update_verification_method(VERIFIED_BY_HASH); return EFI_SUCCESS; + } else { + LogError(L"check_db_hash(db, sha1hash) != DATA_FOUND\n"); } if (cert && check_db_cert(L"db", secure_var, cert, sha256hash) == DATA_FOUND) { verification_method = VERIFIED_BY_CERT; update_verification_method(VERIFIED_BY_CERT); return EFI_SUCCESS; + } else { + LogError(L"check_db_cert(db, sha256hash) != DATA_FOUND\n"); } } @@ -635,12 +671,16 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, verification_method = VERIFIED_BY_HASH; update_verification_method(VERIFIED_BY_HASH); return EFI_SUCCESS; + } else { + LogError(L"check_db_hash(MokList, sha256hash) != DATA_FOUND\n"); } if (cert && check_db_cert(L"MokList", shim_var, cert, sha256hash) == DATA_FOUND) { verification_method = VERIFIED_BY_CERT; update_verification_method(VERIFIED_BY_CERT); return EFI_SUCCESS; + } else { + LogError(L"check_db_cert(MokList, sha256hash) != DATA_FOUND\n"); } update_verification_method(VERIFIED_BY_NOTHING); @@ -883,14 +923,18 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, SumOfBytesHashed += Section->SizeOfRawData; } - /* Hash all remaining data */ - if (datasize > SumOfBytesHashed) { + /* Hash all remaining data up to SecDir if SecDir->Size is not 0 */ + if (datasize > SumOfBytesHashed && context->SecDir->Size) { hashbase = data + SumOfBytesHashed; hashsize = datasize - context->SecDir->Size - SumOfBytesHashed; if ((datasize - SumOfBytesHashed < context->SecDir->Size) || (SumOfBytesHashed + hashsize != context->SecDir->VirtualAddress)) { perror(L"Malformed binary after Attribute Certificate Table\n"); + Print(L"datasize: %u SumOfBytesHashed: %u SecDir->Size: %lu\n", + datasize, SumOfBytesHashed, context->SecDir->Size); + Print(L"hashsize: %u SecDir->VirtualAddress: 0x%08lx\n", + hashsize, context->SecDir->VirtualAddress); status = EFI_INVALID_PARAMETER; goto done; } @@ -902,8 +946,29 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, status = EFI_OUT_OF_RESOURCES; goto done; } + + SumOfBytesHashed += hashsize; } +#if 0 + /* Hash all remaining data */ + if (datasize > SumOfBytesHashed) { + hashbase = data + SumOfBytesHashed; + hashsize = datasize - SumOfBytesHashed; + + check_size(data, datasize_in, hashbase, hashsize); + + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { + perror(L"Unable to generate hash\n"); + status = EFI_OUT_OF_RESOURCES; + goto done; + } + + SumOfBytesHashed += hashsize; + } +#endif + if (!(Sha256Final(sha256ctx, sha256hash)) || !(Sha1Final(sha1ctx, sha1hash))) { perror(L"Unable to finalise hash\n"); @@ -953,13 +1018,13 @@ static EFI_STATUS verify_mok (void) { * Check that the signature is valid and matches the binary */ static EFI_STATUS verify_buffer (char *data, int datasize, - PE_COFF_LOADER_IMAGE_CONTEXT *context) + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash) { - UINT8 sha256hash[SHA256_DIGEST_SIZE]; - UINT8 sha1hash[SHA1_DIGEST_SIZE]; EFI_STATUS status = EFI_SECURITY_VIOLATION; WIN_CERTIFICATE_EFI_PKCS *cert = NULL; unsigned int size = datasize; + EFI_GUID shim_var = SHIM_LOCK_GUID; if (context->SecDir->Size != 0) { if (context->SecDir->Size >= size) { @@ -988,16 +1053,27 @@ static EFI_STATUS verify_buffer (char *data, int datasize, } } + /* + * Clear OpenSSL's error log, because we get some DSO unimplemented + * errors during its intialization, and we don't want those to look + * like they're the reason for validation failures. + */ + drain_openssl_errors(); + status = generate_hash(data, datasize, context, sha256hash, sha1hash); - if (status != EFI_SUCCESS) + if (status != EFI_SUCCESS) { + LogError(L"generate_hash: %r\n", status); return status; + } /* * Check that the MOK database hasn't been modified */ status = verify_mok(); - if (status != EFI_SUCCESS) + if (status != EFI_SUCCESS) { + LogError(L"verify_mok: %r\n", status); return status; + } /* * Ensure that the binary isn't blacklisted @@ -1005,6 +1081,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, status = check_blacklist(cert, sha256hash, sha1hash); if (status != EFI_SUCCESS) { perror(L"Binary is blacklisted\n"); + LogError(L"Binary is blacklisted: %r\n", status); return status; } @@ -1013,10 +1090,15 @@ static EFI_STATUS verify_buffer (char *data, int datasize, * databases */ status = check_whitelist(cert, sha256hash, sha1hash); - if (status == EFI_SUCCESS) + if (status == EFI_SUCCESS) { + drain_openssl_errors(); return status; + } else { + LogError(L"check_whitelist(): %r\n", status); + } if (cert) { +#if defined(ENABLE_SHIM_CERT) /* * Check against the shim build key */ @@ -1026,9 +1108,14 @@ static EFI_STATUS verify_buffer (char *data, int datasize, shim_cert, sizeof(shim_cert), sha256hash, SHA256_DIGEST_SIZE)) { update_verification_method(VERIFIED_BY_CERT); + tpm_measure_variable(L"Shim", shim_var, sizeof(shim_cert), shim_cert); status = EFI_SUCCESS; + drain_openssl_errors(); return status; + } else { + LogError(L"AuthenticodeVerify(shim_cert) failed\n"); } +#endif /* defined(ENABLE_SHIM_CERT) */ /* * And finally, check against shim's built-in key @@ -1039,11 +1126,18 @@ static EFI_STATUS verify_buffer (char *data, int datasize, vendor_cert, vendor_cert_size, sha256hash, SHA256_DIGEST_SIZE)) { update_verification_method(VERIFIED_BY_CERT); + tpm_measure_variable(L"Shim", shim_var, vendor_cert_size, vendor_cert); status = EFI_SUCCESS; + drain_openssl_errors(); return status; + } else { + LogError(L"AuthenticodeVerify(vendor_cert) failed\n"); } } + LogError(L"Binary is not whitelisted\n"); + crypterr(EFI_SECURITY_VIOLATION); + PrintErrors(); status = EFI_SECURITY_VIOLATION; return status; } @@ -1194,6 +1288,8 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, unsigned int alignment, alloc_size; EFI_PHYSICAL_ADDRESS alloc_address; int found_entry_point = 0; + UINT8 sha1hash[SHA1_DIGEST_SIZE]; + UINT8 sha256hash[SHA256_DIGEST_SIZE]; /* * The binary header contains relevant context and section pointers @@ -1207,8 +1303,17 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, /* * We only need to verify the binary if we're in secure mode */ + efi_status = generate_hash(data, datasize, &context, sha256hash, + sha1hash); + if (efi_status != EFI_SUCCESS) + return efi_status; + + /* Measure the binary into the TPM */ + tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, sha1hash, 4); + if (secure_mode ()) { - efi_status = verify_buffer(data, datasize, &context); + efi_status = verify_buffer(data, datasize, &context, + sha256hash, sha1hash); if (EFI_ERROR(efi_status)) { console_error(L"Verification failed", efi_status); @@ -1699,6 +1804,8 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) { EFI_STATUS status = EFI_SUCCESS; PE_COFF_LOADER_IMAGE_CONTEXT context; + UINT8 sha1hash[SHA1_DIGEST_SIZE]; + UINT8 sha256hash[SHA256_DIGEST_SIZE]; loader_is_participating = 1; in_protocol = 1; @@ -1710,7 +1817,11 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) if (status != EFI_SUCCESS) goto done; - status = verify_buffer(buffer, size, &context); + status = generate_hash(buffer, size, &context, sha256hash, sha1hash); + if (status != EFI_SUCCESS) + goto done; + + status = verify_buffer(buffer, size, &context, sha256hash, sha1hash); done: in_protocol = 0; return status; @@ -1810,14 +1921,12 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) if (efi_status != EFI_SUCCESS) { perror(L"Failed to load image %s: %r\n", PathName, efi_status); + PrintErrors(); + ClearErrors(); goto done; } } - /* Measure the binary into the TPM */ - tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, - 9, (CHAR8 *)"Second stage bootloader"); - /* * We need to modify the loaded image protocol entry before running * the new binary, so back it up @@ -1831,6 +1940,8 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) if (efi_status != EFI_SUCCESS) { perror(L"Failed to load image: %r\n", efi_status); + PrintErrors(); + ClearErrors(); CopyMem(li, &li_bak, sizeof(li_bak)); goto done; } @@ -1871,7 +1982,7 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) efi_status = start_image(image_handle, MOK_MANAGER); if (efi_status != EFI_SUCCESS) { Print(L"start_image() returned %r\n", efi_status); - uefi_call_wrapper(BS->Stall, 1, 2000000); + msleep(2000000); return efi_status; } @@ -1881,44 +1992,71 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) if (efi_status != EFI_SUCCESS) { Print(L"start_image() returned %r\n", efi_status); - uefi_call_wrapper(BS->Stall, 1, 2000000); + msleep(2000000); } return efi_status; } /* - * Measure some of the MOK variables into the TPM + * Measure some of the MOK variables into the TPM. We measure the entirety + * of MokList into PCR 14, and also measure the raw MokSBState there. PCR 7 + * will be extended with MokSBState in the Microsoft format, and we'll + * measure any matching hashes or certificates later on in order to behave + * consistently with the PCR 7 spec. */ EFI_STATUS measure_mok() { EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; + EFI_STATUS efi_status, ret = EFI_SUCCESS; UINT8 *Data = NULL; UINTN DataSize = 0; efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid); - if (efi_status != EFI_SUCCESS) - return efi_status; + if (!EFI_ERROR(efi_status)) { + efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, + DataSize, 14, (CHAR8 *)"MokList"); + FreePool(Data); + + if (EFI_ERROR(efi_status)) + ret = efi_status; - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, - DataSize, 14, (CHAR8 *)"MokList"); + } else { + ret = efi_status; + } - FreePool(Data); + efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid); + if (!EFI_ERROR(efi_status)) { + efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, + DataSize, 14, (CHAR8 *)"MokListX"); + FreePool(Data); - if (efi_status != EFI_SUCCESS) - return efi_status; + if (EFI_ERROR(efi_status) && !EFI_ERROR(ret)) + ret = efi_status; + + } else if (!EFI_ERROR(ret)) { + ret = efi_status; + } efi_status = get_variable(L"MokSBState", &Data, &DataSize, shim_lock_guid); + if (!EFI_ERROR(efi_status)) { + efi_status = tpm_measure_variable(L"MokSBState", + shim_lock_guid, + DataSize, Data); + if (!EFI_ERROR(efi_status)) { + efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS) + (UINTN)Data, DataSize, 14, + (CHAR8 *)"MokSBState"); + } - if (efi_status != EFI_SUCCESS) - return efi_status; - - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, - DataSize, 14, (CHAR8 *)"MokSBState"); + FreePool(Data); - FreePool(Data); + if (EFI_ERROR(efi_status) && !EFI_ERROR(ret)) + ret = efi_status; + } else if (!EFI_ERROR(ret)) { + ret = efi_status; + } return efi_status; } @@ -2542,6 +2680,46 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) return EFI_SUCCESS; } +static void * +ossl_malloc(size_t num) +{ + return AllocatePool(num); +} + +static void +ossl_free(void *addr) +{ + FreePool(addr); +} + +static void +init_openssl(void) +{ + CRYPTO_set_mem_functions(ossl_malloc, NULL, ossl_free); + OPENSSL_init(); + CRYPTO_set_mem_functions(ossl_malloc, NULL, ossl_free); + ERR_load_ERR_strings(); + ERR_load_BN_strings(); + ERR_load_RSA_strings(); + ERR_load_DH_strings(); + ERR_load_EVP_strings(); + ERR_load_BUF_strings(); + ERR_load_OBJ_strings(); + ERR_load_PEM_strings(); + ERR_load_X509_strings(); + ERR_load_ASN1_strings(); + ERR_load_CONF_strings(); + ERR_load_CRYPTO_strings(); + ERR_load_COMP_strings(); + ERR_load_BIO_strings(); + ERR_load_PKCS7_strings(); + ERR_load_X509V3_strings(); + ERR_load_PKCS12_strings(); + ERR_load_RAND_strings(); + ERR_load_DSO_strings(); + ERR_load_OCSP_strings(); +} + static SHIM_LOCK shim_lock_interface; static EFI_HANDLE shim_lock_handle; @@ -2695,7 +2873,7 @@ debug_hook(void) #else if (x > 12000) break; - uefi_call_wrapper(BS->Stall, 1, 5000); + msleep(5000); #endif } x = 1; @@ -2730,6 +2908,8 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) */ InitializeLib(image_handle, systab); + init_openssl(); + /* * if SHIM_DEBUG is set, wait for a debugger to attach. */ @@ -2742,10 +2922,10 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) if (efi_status != EFI_SUCCESS && efi_status != EFI_NOT_FOUND) { Print(L"Something has gone seriously wrong: %r\n", efi_status); Print(L"Shim was unable to measure state into the TPM\n"); - systab->BootServices->Stall(5000000); - systab->RuntimeServices->ResetSystem(EfiResetShutdown, - EFI_SECURITY_VIOLATION, - 0, NULL); + msleep(5000000); + uefi_call_wrapper(systab->RuntimeServices->ResetSystem, 4, + EfiResetShutdown, EFI_SECURITY_VIOLATION, + 0, NULL); } /* @@ -2758,7 +2938,7 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) if (EFI_ERROR(efi_status)) { Print(L"Something has gone seriously wrong: %r\n", efi_status); Print(L"shim cannot continue, sorry.\n"); - uefi_call_wrapper(BS->Stall, 1, 5000000); + msleep(5000000); uefi_call_wrapper(systab->RuntimeServices->ResetSystem, 4, EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL); @@ -2769,7 +2949,7 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) */ if (user_insecure_mode) { Print(L"Booting in insecure mode\n"); - uefi_call_wrapper(BS->Stall, 1, 2000000); + msleep(2000000); } /* |