OpenCoreKernel.c 32.7 KB
Newer Older
V
vit9696 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/** @file
  OpenCore driver.

Copyright (c) 2019, vit9696. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

15
#include "ProcessorBind.h"
V
vit9696 已提交
16 17 18 19 20 21
#include <OpenCore.h>

#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcAppleKernelLib.h>
22
#include <Library/OcMiscLib.h>
23
#include <Library/OcAppleImg4Lib.h>
V
vit9696 已提交
24
#include <Library/OcStringLib.h>
V
vit9696 已提交
25 26 27 28 29 30
#include <Library/OcVirtualFsLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>

STATIC OC_STORAGE_CONTEXT  *mOcStorage;
STATIC OC_GLOBAL_CONFIG    *mOcConfiguration;
31
STATIC OC_CPU_INFO         *mOcCpuInfo;
32
STATIC UINT8               mKernelDigest[SHA384_DIGEST_SIZE];
V
vit9696 已提交
33

34 35 36 37 38
STATIC UINT32              mOcDarwinVersion;

STATIC CACHELESS_CONTEXT   mOcCachelessContext;
STATIC BOOLEAN             mOcCachelessInProgress;

39 40 41 42 43 44 45 46 47
//
// Kernel cache types.
//
typedef enum KERNEL_CACHE_TYPE_ {
  CacheTypeCacheless,
  CacheTypeMkext,
  CacheTypePrelinked
} KERNEL_CACHE_TYPE;

V
vit9696 已提交
48
STATIC
49
EFI_STATUS
V
vit9696 已提交
50
OcKernelLoadKextsAndReserve (
51 52 53 54 55 56
  IN  OC_STORAGE_CONTEXT  *Storage,
  IN  OC_GLOBAL_CONFIG    *Config,
  IN  KERNEL_CACHE_TYPE   CacheType,
  OUT UINT32              *ReservedExeSize,
  OUT UINT32              *ReservedInfoSize,
  OUT UINT32              *NumReservedKexts
V
vit9696 已提交
57 58
  )
{
59
  EFI_STATUS           Status;
V
vit9696 已提交
60
  UINT32               Index;
61
  CHAR8                *BundlePath;
62
  CHAR8                *Comment;
V
vit9696 已提交
63 64
  CHAR8                *PlistPath;
  CHAR8                *ExecutablePath;
65
  CHAR16               FullPath[OC_STORAGE_SAFE_PATH_MAX];
V
vit9696 已提交
66
  OC_KERNEL_ADD_ENTRY  *Kext;
V
vit9696 已提交
67

68 69
  *ReservedInfoSize = PRELINK_INFO_RESERVE_SIZE;
  *ReservedExeSize  = 0;
70
  *NumReservedKexts = 0;
V
vit9696 已提交
71 72

  for (Index = 0; Index < Config->Kernel.Add.Count; ++Index) {
V
vit9696 已提交
73 74
    Kext = Config->Kernel.Add.Values[Index];

V
vit9696 已提交
75
    if (!Kext->Enabled) {
V
vit9696 已提交
76 77 78
      continue;
    }

V
vit9696 已提交
79
    if (Kext->PlistDataSize == 0) {
80
      BundlePath     = OC_BLOB_GET (&Kext->BundlePath);
81
      Comment        = OC_BLOB_GET (&Kext->Comment);
V
vit9696 已提交
82
      PlistPath      = OC_BLOB_GET (&Kext->PlistPath);
83
      if (BundlePath[0] == '\0' || PlistPath[0] == '\0') {
V
vit9696 已提交
84
        DEBUG ((DEBUG_ERROR, "OC: Your config has improper for kext info\n"));
V
vit9696 已提交
85
        Kext->Enabled = FALSE;
V
vit9696 已提交
86 87 88
        continue;
      }

89
      Status = OcUnicodeSafeSPrint (
V
vit9696 已提交
90 91 92
        FullPath,
        sizeof (FullPath),
        OPEN_CORE_KEXT_PATH "%a\\%a",
93
        BundlePath,
V
vit9696 已提交
94 95
        PlistPath
        );
96 97 98 99 100 101 102 103 104 105 106
      if (EFI_ERROR (Status)) {
        DEBUG ((
          DEBUG_WARN,
          "OC: Failed to fit kext path %s%a\\%a",
          OPEN_CORE_KEXT_PATH,
          BundlePath,
          PlistPath
          ));
        Kext->Enabled = FALSE;
        continue;
      }
V
vit9696 已提交
107

V
vit9696 已提交
108 109 110
      UnicodeUefiSlashes (FullPath);

      Kext->PlistData = OcStorageReadFileUnicode (
V
vit9696 已提交
111 112
        Storage,
        FullPath,
V
vit9696 已提交
113
        &Kext->PlistDataSize
V
vit9696 已提交
114 115
        );

V
vit9696 已提交
116
      if (Kext->PlistData == NULL) {
117 118 119 120 121 122 123
        DEBUG ((
          DEBUG_ERROR,
          "OC: Plist %s is missing for kext %a (%a)\n",
          FullPath,
          BundlePath,
          Comment
          ));
V
vit9696 已提交
124
        Kext->Enabled = FALSE;
V
vit9696 已提交
125 126 127
        continue;
      }

V
vit9696 已提交
128
      ExecutablePath = OC_BLOB_GET (&Kext->ExecutablePath);
V
vit9696 已提交
129
      if (ExecutablePath[0] != '\0') {
130
        Status = OcUnicodeSafeSPrint (
V
vit9696 已提交
131 132 133
          FullPath,
          sizeof (FullPath),
          OPEN_CORE_KEXT_PATH "%a\\%a",
134
          BundlePath,
V
vit9696 已提交
135 136
          ExecutablePath
          );
137 138 139 140 141 142 143 144 145 146 147 148 149
        if (EFI_ERROR (Status)) {
          DEBUG ((
            DEBUG_WARN,
            "OC: Failed to fit kext path %s%a\\%a",
            OPEN_CORE_KEXT_PATH,
            BundlePath,
            ExecutablePath
            ));
          Kext->Enabled = FALSE;
          FreePool (Kext->PlistData);
          Kext->PlistData = NULL;
          continue;
        }
V
vit9696 已提交
150

V
vit9696 已提交
151 152 153
        UnicodeUefiSlashes (FullPath);

        Kext->ImageData = OcStorageReadFileUnicode (
V
vit9696 已提交
154 155
          Storage,
          FullPath,
V
vit9696 已提交
156
          &Kext->ImageDataSize
V
vit9696 已提交
157 158
          );

V
vit9696 已提交
159
        if (Kext->ImageData == NULL) {
160 161 162 163 164 165 166
          DEBUG ((
            DEBUG_ERROR,
            "OC: Image %s is missing for kext %a (%a)\n",
            FullPath,
            BundlePath,
            Comment
            ));
V
vit9696 已提交
167
          Kext->Enabled = FALSE;
168 169
          FreePool (Kext->PlistData);
          Kext->PlistData = NULL;
V
vit9696 已提交
170
          continue;
V
vit9696 已提交
171 172 173 174
        }
      }
    }

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    if (CacheType == CacheTypeCacheless || CacheType == CacheTypeMkext) {
      Status = MkextReserveKextSize (
        ReservedInfoSize,
        ReservedExeSize,
        Kext->PlistDataSize,
        Kext->ImageData,
        Kext->ImageDataSize
        );
    } else if (CacheType == CacheTypePrelinked) {
      Status = PrelinkedReserveKextSize (
        ReservedInfoSize,
        ReservedExeSize,
        Kext->PlistDataSize,
        Kext->ImageData,
        Kext->ImageDataSize
        );
    }

193 194 195 196 197 198 199 200 201 202 203 204
    if (EFI_ERROR (Status)) {
      DEBUG ((
        DEBUG_ERROR,
        "OC: Failed to fit kext %a (%a)\n",
        BundlePath,
        Comment
        ));
      Kext->Enabled = FALSE;
      FreePool (Kext->PlistData);
      Kext->PlistData = NULL;
      continue;
    }
205 206

    (*NumReservedKexts)++;
V
vit9696 已提交
207 208
  }

209 210 211 212 213
  if (CacheType == CacheTypePrelinked) {
    if (*ReservedExeSize > PRELINKED_KEXTS_MAX_SIZE
      || *ReservedInfoSize + *ReservedExeSize < *ReservedExeSize) {
      return EFI_UNSUPPORTED;
    }
214
  }
V
vit9696 已提交
215

216 217
  DEBUG ((
    DEBUG_INFO,
218 219
    "OC: Kext reservation size info %X exe %X\n",
    *ReservedInfoSize, *ReservedExeSize
220 221
    ));
  return EFI_SUCCESS;
V
vit9696 已提交
222 223
}

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
STATIC
EFI_STATUS
OcKernelApplyQuirk (
  IN     KERNEL_QUIRK_NAME  Quirk,
  IN     KERNEL_CACHE_TYPE  CacheType,
  IN OUT VOID               *Context,
  IN OUT PATCHER_CONTEXT    *KernelPatcher
  )
{
  //
  // Apply kernel quirks to kernel, kext patches to context.
  //
  if (Context == NULL) {
    ASSERT (KernelPatcher != NULL);

    return KernelQuirkApply (Quirk, KernelPatcher);
  } else {
    if (CacheType == CacheTypeCacheless) {
      return CachelessContextAddQuirk ((CACHELESS_CONTEXT *) Context, Quirk);
    } else if (CacheType == CacheTypeMkext) {
      return MkextContextApplyQuirk ((MKEXT_CONTEXT *) Context, Quirk);
    } else if (CacheType == CacheTypePrelinked) {
      return PrelinkedContextApplyQuirk ((PRELINKED_CONTEXT *) Context, Quirk);
    }
  }

  return EFI_UNSUPPORTED;
}

V
vit9696 已提交
253 254 255 256
STATIC
VOID
OcKernelApplyPatches (
  IN     OC_GLOBAL_CONFIG  *Config,
257
  IN     UINT32            DarwinVersion,
258 259
  IN     KERNEL_CACHE_TYPE CacheType,
  IN     VOID              *Context,
V
vit9696 已提交
260 261 262 263 264
  IN OUT UINT8             *Kernel,
  IN     UINT32            Size
  )
{
  EFI_STATUS             Status;
265
  PATCHER_CONTEXT        KernelPatcher;
V
vit9696 已提交
266 267 268 269
  UINT32                 Index;
  PATCHER_GENERIC_PATCH  Patch;
  OC_KERNEL_PATCH_ENTRY  *UserPatch;
  CONST CHAR8            *Target;
270 271 272
  CONST CHAR8            *Comment;
  UINT32                 MaxKernel;
  UINT32                 MinKernel;
V
vit9696 已提交
273 274 275 276 277 278 279 280
  BOOLEAN                IsKernelPatch;

  IsKernelPatch = Context == NULL;

  if (IsKernelPatch) {
    ASSERT (Kernel != NULL);

    Status = PatcherInitContextFromBuffer (
281
      &KernelPatcher,
V
vit9696 已提交
282 283 284 285 286 287 288 289 290 291
      Kernel,
      Size
      );

    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "OC: Kernel patcher kernel init failure - %r\n", Status));
      return;
    }
  }

292
  for (Index = 0; Index < Config->Kernel.Patch.Count; ++Index) {
V
vit9696 已提交
293 294
    UserPatch = Config->Kernel.Patch.Values[Index];
    Target    = OC_BLOB_GET (&UserPatch->Identifier);
295
    Comment   = OC_BLOB_GET (&UserPatch->Comment);
V
vit9696 已提交
296

297
    if (!UserPatch->Enabled || (AsciiStrCmp (Target, "kernel") == 0) != IsKernelPatch) {
V
vit9696 已提交
298 299 300
      continue;
    }

301
    MaxKernel   = OcParseDarwinVersion (OC_BLOB_GET (&UserPatch->MaxKernel));
302
    MinKernel   = OcParseDarwinVersion (OC_BLOB_GET (&UserPatch->MinKernel));
303

304
    if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
305 306
      DEBUG ((
        DEBUG_INFO,
307
        "OC: Kernel patcher skips %a (%a) patch at %u due to version %u <= %u <= %u\n",
308
        Target,
309
        Comment,
310
        Index,
311 312 313
        MinKernel,
        DarwinVersion,
        MaxKernel
314 315 316 317
        ));
      continue;
    }

V
vit9696 已提交
318 319 320 321 322 323 324 325
    //
    // Ignore patch if:
    // - There is nothing to replace.
    // - We have neither symbolic base, nor find data.
    // - Find and replace mismatch in size.
    // - Mask and ReplaceMask mismatch in size when are available.
    //
    if (UserPatch->Replace.Size == 0
326
      || (OC_BLOB_GET (&UserPatch->Base)[0] == '\0' && UserPatch->Find.Size != UserPatch->Replace.Size)
V
vit9696 已提交
327 328
      || (UserPatch->Mask.Size > 0 && UserPatch->Find.Size != UserPatch->Mask.Size)
      || (UserPatch->ReplaceMask.Size > 0 && UserPatch->Find.Size != UserPatch->ReplaceMask.Size)) {
329
      DEBUG ((DEBUG_ERROR, "OC: Kernel patch %u for %a (%a) is borked\n", Index, Target, Comment));
V
vit9696 已提交
330 331 332 333 334
      continue;
    }

    ZeroMem (&Patch, sizeof (Patch));

335 336 337 338
    if (OC_BLOB_GET (&UserPatch->Comment)[0] != '\0') {
      Patch.Comment  = OC_BLOB_GET (&UserPatch->Comment);
    }

339
    if (OC_BLOB_GET (&UserPatch->Base)[0] != '\0') {
V
vit9696 已提交
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
      Patch.Base  = OC_BLOB_GET (&UserPatch->Base);
    }

    if (UserPatch->Find.Size > 0) {
      Patch.Find  = OC_BLOB_GET (&UserPatch->Find);
    }

    Patch.Replace = OC_BLOB_GET (&UserPatch->Replace);

    if (UserPatch->Mask.Size > 0) {
      Patch.Mask  = OC_BLOB_GET (&UserPatch->Mask);
    }

    if (UserPatch->ReplaceMask.Size > 0) {
      Patch.ReplaceMask = OC_BLOB_GET (&UserPatch->ReplaceMask);
    }

    Patch.Size    = UserPatch->Replace.Size;
    Patch.Count   = UserPatch->Count;
    Patch.Skip    = UserPatch->Skip;
    Patch.Limit   = UserPatch->Limit;

362 363 364 365 366 367 368 369 370 371 372 373
    if (IsKernelPatch) {
      Status = PatcherApplyGenericPatch (&KernelPatcher, &Patch);
    } else {
      if (CacheType == CacheTypeCacheless) {
        Status = CachelessContextAddPatch ((CACHELESS_CONTEXT *) Context, Target, &Patch);
      } else if (CacheType == CacheTypeMkext) {
        Status = MkextContextApplyPatch ((MKEXT_CONTEXT *) Context, Target, &Patch);
      } else if (CacheType == CacheTypePrelinked) {
        Status = PrelinkedContextApplyPatch ((PRELINKED_CONTEXT *) Context, Target, &Patch);
      }
    }

V
vit9696 已提交
374
    DEBUG ((
375
      EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
376
      "OC: Kernel patcher result %u for %a (%a) - %r\n",
V
vit9696 已提交
377 378
      Index,
      Target,
379
      Comment,
V
vit9696 已提交
380 381
      Status
      ));
V
vit9696 已提交
382
  }
383 384 385

  if (!IsKernelPatch) {
    if (Config->Kernel.Quirks.AppleCpuPmCfgLock) {
386
      OcKernelApplyQuirk (KernelQuirkAppleCpuPmCfgLock, CacheType, Context, NULL);
387 388 389
    }

    if (Config->Kernel.Quirks.ExternalDiskIcons) {
390
      OcKernelApplyQuirk (KernelQuirkExternalDiskIcons, CacheType, Context, NULL);
391 392
    }

393
    if (Config->Kernel.Quirks.ThirdPartyDrives) {
394
      OcKernelApplyQuirk (KernelQuirkThirdPartyDrives, CacheType, Context, NULL);
395 396 397
    }

    if (Config->Kernel.Quirks.XhciPortLimit) {
398 399 400
      OcKernelApplyQuirk (KernelQuirkXhciPortLimit1, CacheType, Context, NULL);
      OcKernelApplyQuirk (KernelQuirkXhciPortLimit2, CacheType, Context, NULL);
      OcKernelApplyQuirk (KernelQuirkXhciPortLimit3, CacheType, Context, NULL);
401
    }
402 403

    if (Config->Kernel.Quirks.DisableIoMapper) {
404
      OcKernelApplyQuirk (KernelQuirkDisableIoMapper, CacheType, Context, NULL);
405
    }
406

407
    if (Config->Kernel.Quirks.DisableRtcChecksum) {
408
      OcKernelApplyQuirk (KernelQuirkDisableRtcChecksum, CacheType, Context, NULL);
409 410
    }

411
    if (Config->Kernel.Quirks.IncreasePciBarSize) {
412
      OcKernelApplyQuirk (KernelQuirkIncreasePciBarSize, CacheType, Context, NULL);     
413 414
    }

415
    if (Config->Kernel.Quirks.CustomSmbiosGuid) {
416 417
      OcKernelApplyQuirk (KernelQuirkCustomSmbiosGuid1, CacheType, Context, NULL);
      OcKernelApplyQuirk (KernelQuirkCustomSmbiosGuid2, CacheType, Context, NULL);
418
    }
419 420

    if (Config->Kernel.Quirks.DummyPowerManagement) {
421
      OcKernelApplyQuirk (KernelQuirkDummyPowerManagement, CacheType, Context, NULL);
422
    }
423 424
  } else {
    if (Config->Kernel.Quirks.AppleXcpmCfgLock) {
425
      OcKernelApplyQuirk (KernelQuirkAppleXcpmCfgLock, CacheType, NULL, &KernelPatcher);
426
    }
427

428
    if (Config->Kernel.Quirks.AppleXcpmExtraMsrs) {
429
      OcKernelApplyQuirk (KernelQuirkAppleXcpmExtraMsrs, CacheType, NULL, &KernelPatcher);
430 431
    }

432
    if (Config->Kernel.Quirks.AppleXcpmForceBoost) {
433
      OcKernelApplyQuirk (KernelQuirkAppleXcpmForceBoost, CacheType, NULL, &KernelPatcher);
434 435
    }

436
    if (Config->Kernel.Quirks.PanicNoKextDump) {
437
      OcKernelApplyQuirk (KernelQuirkPanicNoKextDump, CacheType, NULL, &KernelPatcher);
438 439
    }

440 441 442 443 444
    if (Config->Kernel.Emulate.Cpuid1Data[0] != 0
      || Config->Kernel.Emulate.Cpuid1Data[1] != 0
      || Config->Kernel.Emulate.Cpuid1Data[2] != 0
      || Config->Kernel.Emulate.Cpuid1Data[3] != 0) {
      PatchKernelCpuId (
445
        &KernelPatcher,
446 447 448 449 450
        mOcCpuInfo,
        Config->Kernel.Emulate.Cpuid1Data,
        Config->Kernel.Emulate.Cpuid1Mask
        );
    }
V
vit9696 已提交
451 452

    if (Config->Kernel.Quirks.LapicKernelPanic) {
453
      OcKernelApplyQuirk (KernelQuirkLapicKernelPanic, CacheType, NULL, &KernelPatcher);
V
vit9696 已提交
454
    }
455 456

    if (Config->Kernel.Quirks.PowerTimeoutKernelPanic) {
457
      OcKernelApplyQuirk (KernelQuirkPowerTimeoutKernelPanic, CacheType, NULL, &KernelPatcher);
458
    }
459 460 461 462 463 464 465
  }
}

STATIC
VOID
OcKernelBlockKexts (
  IN     OC_GLOBAL_CONFIG  *Config,
466
  IN     UINT32            DarwinVersion,
467 468 469 470 471 472 473 474
  IN     PRELINKED_CONTEXT *Context
  )
{
  EFI_STATUS             Status;
  PATCHER_CONTEXT        Patcher;
  UINT32                 Index;
  OC_KERNEL_BLOCK_ENTRY  *Kext;
  CONST CHAR8            *Target;
475 476 477
  CONST CHAR8            *Comment;
  UINT32                 MaxKernel;
  UINT32                 MinKernel;
478 479

  for (Index = 0; Index < Config->Kernel.Block.Count; ++Index) {
480 481 482
    Kext    = Config->Kernel.Block.Values[Index];
    Target  = OC_BLOB_GET (&Kext->Identifier);
    Comment = OC_BLOB_GET (&Kext->Comment);
483

V
vit9696 已提交
484
    if (!Kext->Enabled) {
485 486 487
      continue;
    }

488
    MaxKernel = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MaxKernel));
489
    MinKernel = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MinKernel));
490

491
    if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
492 493
      DEBUG ((
        DEBUG_INFO,
494
        "OC: Prelink blocker skips %a (%a) block at %u due to version %u <= %u <= %u\n",
495
        Target,
496
        Comment,
497
        Index,
498 499 500
        MinKernel,
        DarwinVersion,
        MaxKernel
501 502 503 504 505 506 507 508 509 510 511
        ));
      continue;
    }

    Status = PatcherInitContextFromPrelinked (
      &Patcher,
      Context,
      Target
      );

    if (EFI_ERROR (Status)) {
512
      DEBUG ((DEBUG_WARN, "OC: Prelink blocker %a (%a) init failure - %r\n", Target, Comment, Status));
513 514 515 516
      continue;
    }

    Status = PatcherBlockKext (&Patcher);
517 518 519

    DEBUG ((
      EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
520
      "OC: Prelink blocker %a (%a) - %r\n",
521
      Target,
522
      Comment,
523 524
      Status
      ));
525
  }
V
vit9696 已提交
526 527
}

V
vit9696 已提交
528 529 530 531
STATIC
EFI_STATUS
OcKernelProcessPrelinked (
  IN     OC_GLOBAL_CONFIG  *Config,
532
  IN     UINT32            DarwinVersion,
V
vit9696 已提交
533 534
  IN OUT UINT8             *Kernel,
  IN     UINT32            *KernelSize,
535 536 537
  IN     UINT32            AllocatedSize,
  IN     UINT32            LinkedExpansion,
  IN     UINT32            ReservedExeSize
V
vit9696 已提交
538 539
  )
{
540 541
  EFI_STATUS           Status;
  PRELINKED_CONTEXT    Context;
542
  CHAR8                *BundlePath;
543
  CHAR8                *ExecutablePath;
544
  CHAR8                *Comment;
545
  UINT32               Index;
546
  CHAR8                FullPath[OC_STORAGE_SAFE_PATH_MAX];
547
  OC_KERNEL_ADD_ENTRY  *Kext;
548 549
  UINT32               MaxKernel;
  UINT32               MinKernel;
V
vit9696 已提交
550 551 552 553

  Status = PrelinkedContextInit (&Context, Kernel, *KernelSize, AllocatedSize);

  if (!EFI_ERROR (Status)) {
554
    OcKernelApplyPatches (Config, DarwinVersion, CacheTypePrelinked, &Context, NULL, 0);
555 556

    OcKernelBlockKexts (Config, DarwinVersion, &Context);
V
vit9696 已提交
557

558 559 560 561 562
    Status = PrelinkedInjectPrepare (
      &Context,
      LinkedExpansion,
      ReservedExeSize
      );
V
vit9696 已提交
563 564
    if (!EFI_ERROR (Status)) {
      for (Index = 0; Index < Config->Kernel.Add.Count; ++Index) {
565 566
        Kext = Config->Kernel.Add.Values[Index];

V
vit9696 已提交
567
        if (!Kext->Enabled || Kext->PlistDataSize == 0) {
568 569 570
          continue;
        }

571
        BundlePath  = OC_BLOB_GET (&Kext->BundlePath);
572 573
        Comment     = OC_BLOB_GET (&Kext->Comment);
        MaxKernel   = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MaxKernel));
574
        MinKernel   = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MinKernel));
575

576
        if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
577 578
          DEBUG ((
            DEBUG_INFO,
579
            "OC: Prelink injection skips %a (%a) kext at %u due to version %u <= %u <= %u\n",
580
            BundlePath,
581
            Comment,
582
            Index,
583 584 585
            MinKernel,
            DarwinVersion,
            MaxKernel
586
            ));
V
vit9696 已提交
587 588 589
          continue;
        }

590 591 592 593 594 595
        Status = OcAsciiSafeSPrint (FullPath, sizeof (FullPath), "/Library/Extensions/%a", BundlePath);
        if (EFI_ERROR (Status)) {
          DEBUG ((DEBUG_WARN, "OC: Failed to fit kext path /Library/Extensions/%a", BundlePath));
          continue;
        }

596 597
        if (Kext->ImageData != NULL) {
          ExecutablePath = OC_BLOB_GET (&Kext->ExecutablePath);
V
vit9696 已提交
598 599 600 601 602 603 604
        } else {
          ExecutablePath = NULL;
        }

        Status = PrelinkedInjectKext (
          &Context,
          FullPath,
605 606
          Kext->PlistData,
          Kext->PlistDataSize,
V
vit9696 已提交
607
          ExecutablePath,
608 609
          Kext->ImageData,
          Kext->ImageDataSize
V
vit9696 已提交
610 611
          );

612 613
        DEBUG ((
          EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
614
          "OC: Prelink injection %a (%a) - %r\n",
615
          BundlePath,
616
          Comment,
617 618
          Status
          ));
V
vit9696 已提交
619 620
      }

621 622 623 624 625 626 627 628
      DEBUG ((
        DEBUG_INFO,
        "OC: Prelink size %u kext offset %u reserved %u\n",
        Context.PrelinkedSize,
        Context.KextsFileOffset,
        ReservedExeSize
        ));

629 630
      ASSERT (Context.PrelinkedSize - Context.KextsFileOffset <= ReservedExeSize);

V
vit9696 已提交
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
      Status = PrelinkedInjectComplete (&Context);
      if (EFI_ERROR (Status)) {
        DEBUG ((DEBUG_WARN, "OC: Prelink insertion error - %r\n", Status));
      }
    } else {
      DEBUG ((DEBUG_WARN, "OC: Prelink inject prepare error - %r\n", Status));
    }

    *KernelSize = Context.PrelinkedSize;

    PrelinkedContextFree (&Context);
  }

  return Status;
}

647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
STATIC
EFI_STATUS
OcKernelProcessMkext (
  IN     OC_GLOBAL_CONFIG  *Config,
  IN     UINT32            DarwinVersion,
  IN OUT UINT8             *Mkext,
  IN OUT UINT32            *MkextSize,
  IN     UINT32            AllocatedSize
  )
{
  EFI_STATUS            Status;
  MKEXT_CONTEXT         Context;
  CHAR8                 *BundlePath;
  CHAR8                 *Comment;
  UINT32                Index;
  CHAR8                 FullPath[OC_STORAGE_SAFE_PATH_MAX];
  OC_KERNEL_ADD_ENTRY   *Kext;
  UINT32                MaxKernel;
  UINT32                MinKernel;

  Status = MkextContextInit (&Context, Mkext, *MkextSize, AllocatedSize);
  if (EFI_ERROR (Status)) {
    return Status;
  }

672 673
  OcKernelApplyPatches (Config, DarwinVersion, CacheTypeMkext, &Context, NULL, 0);

674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
  for (Index = 0; Index < Config->Kernel.Add.Count; ++Index) {
    Kext = Config->Kernel.Add.Values[Index];

    if (!Kext->Enabled || Kext->PlistDataSize == 0) {
      continue;
    }

    BundlePath  = OC_BLOB_GET (&Kext->BundlePath);
    Comment     = OC_BLOB_GET (&Kext->Comment);
    MaxKernel   = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MaxKernel));
    MinKernel   = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MinKernel));

    if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
      DEBUG ((
        DEBUG_INFO,
        "OC: Mkext injection skips %a (%a) kext at %u due to version %u <= %u <= %u\n",
        BundlePath,
        Comment,
        Index,
        MinKernel,
        DarwinVersion,
        MaxKernel
        ));
      continue;
    }

    Status = OcAsciiSafeSPrint (FullPath, sizeof (FullPath), "/Library/Extensions/%a", BundlePath);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_WARN, "OC: Failed to fit kext path /Library/Extensions/%a", BundlePath));
      continue;
    }

    Status = MkextInjectKext (
      &Context,
      FullPath,
      Kext->PlistData,
      Kext->PlistDataSize,
      Kext->ImageData,
      Kext->ImageDataSize
      );

    DEBUG ((
      EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
      "OC: Mkext injection %a (%a) - %r\n",
      BundlePath,
      Comment,
      Status
      ));
  }

  Status = MkextInjectPatchComplete (&Context);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_WARN, "OC: Mkext insertion error - %r\n", Status));
  }

  *MkextSize = Context.MkextSize;

  MkextContextFree (&Context);
  return Status;
}

735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
STATIC
EFI_STATUS
OcKernelInitCacheless (
  IN     OC_GLOBAL_CONFIG       *Config,
  IN     CACHELESS_CONTEXT      *Context,
  IN     UINT32                 DarwinVersion,
  IN     CHAR16                 *FileName,
  IN     EFI_FILE_PROTOCOL      *ExtensionsDir,
     OUT EFI_FILE_PROTOCOL      **File
  )
{
  EFI_STATUS            Status;
  UINT32                Index;

  OC_KERNEL_ADD_ENTRY   *Kext;
  CHAR8                 *BundlePath;
  CHAR8                 *Comment;
  UINT32                MaxKernel;
  UINT32                MinKernel;

  Status = CachelessContextInit (Context, FileName, ExtensionsDir);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Add kexts into cacheless context.
  //
  for (Index = 0; Index < Config->Kernel.Add.Count; Index++) {
    Kext = Config->Kernel.Add.Values[Index];

    if (!Kext->Enabled || Kext->PlistDataSize == 0) {
      continue;
    }

    BundlePath  = OC_BLOB_GET (&Kext->BundlePath);
    Comment     = OC_BLOB_GET (&Kext->Comment);
    MaxKernel   = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MaxKernel));
    MinKernel   = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MinKernel));

    if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
      DEBUG ((
        DEBUG_INFO,
        "OC: Cacheless injection skips %a (%a) kext at %u due to version %u <= %u <= %u\n",
        BundlePath,
        Comment,
        Index,
        MinKernel,
        DarwinVersion,
        MaxKernel
        ));
      continue;
    }

    Status = CachelessContextAddKext (
      Context,
      Kext->PlistData,
      Kext->PlistDataSize,
      Kext->ImageData,
      Kext->ImageDataSize
      );
    if (EFI_ERROR (Status)) {
      CachelessContextFree (Context);
      return Status;
    }
  }

802 803 804 805 806
  //
  // Process patches and blocks.
  //
  OcKernelApplyPatches (Config, DarwinVersion, CacheTypeCacheless, Context, NULL, 0);

807 808 809
  return CachelessContextOverlayExtensionsDir (Context, File);
}

V
vit9696 已提交
810 811 812 813 814 815 816 817 818 819 820 821
STATIC
EFI_STATUS
EFIAPI
OcKernelFileOpen (
  IN  EFI_FILE_PROTOCOL       *This,
  OUT EFI_FILE_PROTOCOL       **NewHandle,
  IN  CHAR16                  *FileName,
  IN  UINT64                  OpenMode,
  IN  UINT64                  Attributes
  )
{
  EFI_STATUS         Status;
822 823
  CONST CHAR8        *ForceCacheType;
  KERNEL_CACHE_TYPE  MaxCacheTypeAllowed;
824
  BOOLEAN            Result;
V
vit9696 已提交
825 826 827 828 829 830 831
  UINT8              *Kernel;
  UINT32             KernelSize;
  UINT32             AllocatedSize;
  CHAR16             *FileNameCopy;
  EFI_FILE_PROTOCOL  *VirtualFileHandle;
  EFI_STATUS         PrelinkedStatus;
  EFI_TIME           ModificationTime;
832 833
  UINT32             ReservedInfoSize;
  UINT32             ReservedExeSize;
834
  UINT32             NumReservedKexts;
835 836
  UINT32             LinkedExpansion;
  UINT32             ReservedFullSize;
V
vit9696 已提交
837

838 839 840 841 842 843 844 845 846 847 848 849
  //
  // Prevent access to cache files depending on maximum cache type allowed.
  //
  ForceCacheType = OC_BLOB_GET (&mOcConfiguration->Kernel.Quirks.ForceKernelCache);
  if (AsciiStrCmp (ForceCacheType, "Cacheless") == 0) {
    MaxCacheTypeAllowed = CacheTypeCacheless;
  } else if (AsciiStrCmp (ForceCacheType, "Mkext") == 0) {
    MaxCacheTypeAllowed = CacheTypeMkext;
  } else {
    MaxCacheTypeAllowed = CacheTypePrelinked;
  }

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
  //
  // Hook injected OcXXXXXXXX.kext reads from /S/L/E.
  //
  if (mOcCachelessInProgress
    && OpenMode == EFI_FILE_MODE_READ
    && StrnCmp (FileName, L"System\\Library\\Extensions\\Oc", L_STR_LEN (L"System\\Library\\Extensions\\Oc")) == 0) {
    Status = CachelessContextPerformInject (&mOcCachelessContext, FileName, NewHandle);
    DEBUG ((
      DEBUG_INFO,
      "OC: Hooking SLE injected file %s with %u mode gave - %r\n",
      FileName,
      (UINT32) OpenMode,
      Status
      ));

    return Status;
  }

V
vit9696 已提交
868
  Status = SafeFileOpen (This, NewHandle, FileName, OpenMode, Attributes);
V
vit9696 已提交
869

870 871
  DEBUG ((
    DEBUG_VERBOSE,
872
    "OC: Opening file %s with %u mode gave - %r\n",
873 874 875 876 877
    FileName,
    (UINT32) OpenMode,
    Status
    ));

V
vit9696 已提交
878 879 880 881 882 883 884 885
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // boot.efi uses /S/L/K/kernel as is to determine valid filesystem.
  // Just skip it to speedup the boot process.
  // On 10.9 mach_kernel is loaded for manual linking aferwards, so we cannot skip it.
886
  // We also want to skip files named "kernel" that are part of kext bundles, and im4m.
V
vit9696 已提交
887 888
  //
  if (OpenMode == EFI_FILE_MODE_READ
889
    && OcStriStr (FileName, L"kernel") != NULL
890 891 892
    && StrCmp (FileName, L"System\\Library\\Kernels\\kernel") != 0
    && OcStriStr (FileName, L".kext") == NULL
    && OcStriStr (FileName, L".im4m") == NULL) {
V
vit9696 已提交
893

894 895 896
    OcKernelLoadKextsAndReserve (
      mOcStorage,
      mOcConfiguration,
897
      CacheTypePrelinked,
898
      &ReservedExeSize,
899 900
      &ReservedInfoSize,
      &NumReservedKexts
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
      );

    LinkedExpansion = KcGetSegmentFixupChainsSize (ReservedExeSize);
    if (LinkedExpansion == 0) {
      return EFI_UNSUPPORTED;
    }

    Result = OcOverflowTriAddU32 (
      ReservedInfoSize,
      ReservedExeSize,
      LinkedExpansion,
      &ReservedFullSize
      );
    if (Result) {
      return EFI_UNSUPPORTED;
    }

918
    DEBUG ((DEBUG_INFO, "OC: Trying XNU hook on %s\n", FileName));
V
vit9696 已提交
919 920 921 922 923
    Status = ReadAppleKernel (
      *NewHandle,
      &Kernel,
      &KernelSize,
      &AllocatedSize,
924 925
      ReservedFullSize,
      mKernelDigest
V
vit9696 已提交
926
      );
927 928 929 930 931 932 933 934 935 936
    DEBUG ((
      DEBUG_INFO,
      "OC: Result of XNU hook on %s (%02X%02X%02X%02X) is %r\n",
      FileName,
      mKernelDigest[0],
      mKernelDigest[1],
      mKernelDigest[2],
      mKernelDigest[3],
      Status
      ));
V
vit9696 已提交
937 938

    if (!EFI_ERROR (Status)) {
939
      mOcDarwinVersion = OcKernelReadDarwinVersion (Kernel, KernelSize);
940
      OcKernelApplyPatches (mOcConfiguration, mOcDarwinVersion, 0, NULL, Kernel, KernelSize);
V
vit9696 已提交
941

942 943 944 945 946 947 948 949 950 951 952 953 954 955 956
      //
      // Disable prelinked if forcing mkext or cacheless, but only on appropriate versions.
      //
      if ((OcStriStr (FileName, L"kernelcache") != NULL || OcStriStr (FileName, L"prelinkedkernel") != NULL)
        && ((MaxCacheTypeAllowed == CacheTypeMkext && mOcDarwinVersion <= KERNEL_VERSION_SNOW_LEOPARD_MAX)
        || (MaxCacheTypeAllowed == CacheTypeCacheless && mOcDarwinVersion <= KERNEL_VERSION_MAVERICKS_MAX))) {
        DEBUG ((DEBUG_INFO, "OC: Blocking prelinked due to ForceKernelCache=%s: %a\n", FileName, ForceCacheType));

        FreePool (Kernel);
        (*NewHandle)->Close(*NewHandle);
        *NewHandle = NULL;

        return EFI_NOT_FOUND;
      }

V
vit9696 已提交
957 958
      PrelinkedStatus = OcKernelProcessPrelinked (
        mOcConfiguration,
959
        mOcDarwinVersion,
V
vit9696 已提交
960 961
        Kernel,
        &KernelSize,
962 963 964
        AllocatedSize,
        LinkedExpansion,
        ReservedExeSize
V
vit9696 已提交
965 966
        );

967
      DEBUG ((DEBUG_INFO, "OC: Prelinked status - %r\n", PrelinkedStatus));
V
vit9696 已提交
968

G
Goldfish64 已提交
969
      Status = GetFileModificationTime (*NewHandle, &ModificationTime);
V
vit9696 已提交
970 971 972 973 974 975 976 977 978 979 980
      if (EFI_ERROR (Status)) {
        ZeroMem (&ModificationTime, sizeof (ModificationTime));
      }

      (*NewHandle)->Close(*NewHandle);

      //
      // This was our file, yet firmware is dying.
      //
      FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName);
      if (FileNameCopy == NULL) {
981
        DEBUG ((DEBUG_WARN, "OC: Failed to allocate kernel name (%a) copy\n", FileName));
V
vit9696 已提交
982 983 984 985 986 987
        FreePool (Kernel);
        return EFI_OUT_OF_RESOURCES;
      }

      Status = CreateVirtualFile (FileNameCopy, Kernel, KernelSize, &ModificationTime, &VirtualFileHandle);
      if (EFI_ERROR (Status)) {
988
        DEBUG ((DEBUG_WARN, "OC: Failed to virtualise kernel file (%a)\n", FileName));
V
vit9696 已提交
989 990 991 992 993
        FreePool (Kernel);
        FreePool (FileNameCopy);
        return EFI_OUT_OF_RESOURCES;
      }

994 995
      OcAppleImg4RegisterOverride (mKernelDigest, Kernel, KernelSize);

V
vit9696 已提交
996 997 998 999 1000 1001 1002 1003
      //
      // Return our handle.
      //
      *NewHandle = VirtualFileHandle;
      return EFI_SUCCESS;
    }
  }

1004 1005
  if (OpenMode == EFI_FILE_MODE_READ
    && OcStriStr (FileName, L"Extensions.mkext") != NULL) {
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016

    //
    // Disable mkext booting if forcing cacheless.
    //
    if (MaxCacheTypeAllowed == CacheTypeCacheless) {
      DEBUG ((DEBUG_INFO, "OC: Blocking mkext due to ForceKernelCache=%s: %a\n", FileName, ForceCacheType));
      (*NewHandle)->Close(*NewHandle);
      *NewHandle = NULL;

      return EFI_NOT_FOUND;
    }
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
    
    OcKernelLoadKextsAndReserve (
      mOcStorage,
      mOcConfiguration,
      CacheTypeMkext,
      &ReservedExeSize,
      &ReservedInfoSize,
      &NumReservedKexts
      );

    Result = OcOverflowAddU32 (
      ReservedInfoSize,
      ReservedExeSize,
      &ReservedFullSize
      );
    if (Result) {
      return EFI_UNSUPPORTED;
    }

    DEBUG ((DEBUG_INFO, "OC: Trying mkext hook on %s\n", FileName));
    Status = ReadAppleMkext (
      *NewHandle,
      MachCpuTypeX8664,
      &Kernel,
      &KernelSize,
      &AllocatedSize,
      ReservedFullSize,
      NumReservedKexts
      );
    DEBUG ((DEBUG_INFO, "OC: Result of mkext hook on %s is %r\n", FileName, Status));

    if (!EFI_ERROR (Status)) {
      //
      // Process mkext.
      //
      Status = OcKernelProcessMkext (mOcConfiguration, mOcDarwinVersion, Kernel, &KernelSize, AllocatedSize);
      DEBUG ((DEBUG_INFO, "OC: Mkext status - %r\n", Status));
      if (!EFI_ERROR (Status)) {
        Status = GetFileModificationTime (*NewHandle, &ModificationTime);
        if (EFI_ERROR (Status)) {
          ZeroMem (&ModificationTime, sizeof (ModificationTime));
        }

        (*NewHandle)->Close(*NewHandle);

        Status = CreateVirtualFileFileNameCopy (FileName, Kernel, KernelSize, &ModificationTime, &VirtualFileHandle);
        if (EFI_ERROR (Status)) {
          DEBUG ((DEBUG_WARN, "OC: Failed to virtualise mkext file (%a) - %r\n", FileName, Status));
          FreePool (Kernel);
          return EFI_OUT_OF_RESOURCES;
        }

        *NewHandle = VirtualFileHandle;
        return EFI_SUCCESS;
      } else {
        FreePool (Kernel);
      }
    }
  }

1077 1078 1079 1080 1081 1082
  //
  // Hook /S/L/E for cacheless boots.
  //
  if (OpenMode == EFI_FILE_MODE_READ
    && StrCmp (FileName, L"System\\Library\\Extensions") == 0) {

1083 1084 1085 1086 1087 1088
    //
    // Free existing context if we are re-opening Extensions directory.
    //
    if (mOcCachelessInProgress) {
      CachelessContextFree (&mOcCachelessContext);
    }
1089 1090 1091 1092 1093
    mOcCachelessInProgress = FALSE;

    OcKernelLoadKextsAndReserve (
      mOcStorage,
      mOcConfiguration,
1094
      CacheTypeCacheless,
1095
      &ReservedExeSize,
1096 1097
      &ReservedInfoSize,
      &NumReservedKexts
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
      );

    //
    // Initialize Extensions directory overlay for cacheless injection.
    //
    Status = OcKernelInitCacheless (
      mOcConfiguration,
      &mOcCachelessContext,
      mOcDarwinVersion,
      FileName,
      *NewHandle,
      &VirtualFileHandle
      );
    
    DEBUG ((DEBUG_INFO, "OC: Result of SLE hook on %s is %r\n", FileName, Status));

    if (!EFI_ERROR (Status)) {
      mOcCachelessInProgress  = TRUE;
      *NewHandle              = VirtualFileHandle;
      return EFI_SUCCESS;
    }
  }

  //
  // Hook /S/L/E contents for processing during cacheless boots.
  //
  if (mOcCachelessInProgress
    && OpenMode == EFI_FILE_MODE_READ
    && StrnCmp (FileName, L"System\\Library\\Extensions\\", L_STR_LEN (L"System\\Library\\Extensions\\")) == 0) {
      Status = CachelessContextHookBuiltin (
        &mOcCachelessContext,
        FileName,
        *NewHandle,
        &VirtualFileHandle
        );

      if (!EFI_ERROR (Status) && VirtualFileHandle != NULL) {
        *NewHandle = VirtualFileHandle;
        return EFI_SUCCESS;
      }
  }

1140
  //
1141
  // This is not Apple kernel, just return the original file.
1142 1143 1144
  // We recurse the filtering to additionally catch com.apple.boot.[RPS] directories.
  //
  return CreateRealFile (*NewHandle, OcKernelFileOpen, TRUE, NewHandle);
V
vit9696 已提交
1145 1146 1147 1148 1149
}

VOID
OcLoadKernelSupport (
  IN OC_STORAGE_CONTEXT  *Storage,
1150 1151
  IN OC_GLOBAL_CONFIG    *Config,
  IN OC_CPU_INFO         *CpuInfo
V
vit9696 已提交
1152 1153 1154 1155 1156 1157 1158
  )
{
  EFI_STATUS  Status;

  Status = EnableVirtualFs (gBS, OcKernelFileOpen);

  if (!EFI_ERROR (Status)) {
1159 1160 1161 1162 1163
    mOcStorage              = Storage;
    mOcConfiguration        = Config;
    mOcCpuInfo              = CpuInfo;
    mOcDarwinVersion        = 0;
    mOcCachelessInProgress  = FALSE;
V
vit9696 已提交
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
  } else {
    DEBUG ((DEBUG_ERROR, "OC: Failed to enable vfs - %r\n", Status));
  }
}

VOID
OcUnloadKernelSupport (
  VOID
  )
{
  EFI_STATUS  Status;

  if (mOcStorage != NULL) {
    Status = DisableVirtualFs (gBS);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "OC: Failed to disable vfs - %r\n", Status));
    }
    mOcStorage       = NULL;
    mOcConfiguration = NULL;
  }
}