/** @file OpenCore driver. Copyright (c) 2019, vit9696. All rights reserved.
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. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include STATIC VOID OcStoreLoadPath ( IN EFI_DEVICE_PATH_PROTOCOL *LoadPath OPTIONAL ) { EFI_STATUS Status; CHAR16 *DevicePath; CHAR8 OutPath[256]; if (LoadPath != NULL) { DevicePath = ConvertDevicePathToText (LoadPath, FALSE, FALSE); if (DevicePath != NULL) { AsciiSPrint (OutPath, sizeof (OutPath), "%s", DevicePath); FreePool (DevicePath); } else { LoadPath = NULL; } } if (LoadPath == NULL) { AsciiSPrint (OutPath, sizeof (OutPath), "Unknown"); } Status = gRT->SetVariable ( OC_LOG_VARIABLE_PATH, &gOcVendorVariableGuid, OPEN_CORE_NVRAM_ATTR, AsciiStrSize (OutPath), OutPath ); DEBUG (( EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO, "OC: Setting NVRAM %g:%a = %a - %r\n", &gOcVendorVariableGuid, OC_LOG_VARIABLE_PATH, OutPath, Status )); } STATIC EFI_STATUS EFIAPI OcToolLoadEntry ( IN VOID *Context, IN OC_BOOT_ENTRY *ChosenEntry, OUT VOID **Data, OUT UINT32 *DataSize, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL ) { CHAR16 ToolPath[64]; OC_STORAGE_CONTEXT *Storage; UnicodeSPrint ( ToolPath, sizeof (ToolPath), OPEN_CORE_TOOL_PATH "%s", ChosenEntry->PathName ); Storage = (OC_STORAGE_CONTEXT *) Context; *Data = OcStorageReadFileUnicode ( Storage, ToolPath, DataSize ); if (*Data == NULL) { DEBUG (( DEBUG_ERROR, "OC: Tool %s cannot be found!\n", ToolPath )); return EFI_NOT_FOUND; } if (DevicePath != NULL) { *DevicePath = Storage->DummyDevicePath; } return EFI_SUCCESS; } EFI_STATUS OcMiscEarlyInit ( IN OC_STORAGE_CONTEXT *Storage, OUT OC_GLOBAL_CONFIG *Config, IN RSA_PUBLIC_KEY *VaultKey OPTIONAL ) { EFI_STATUS Status; CHAR8 *ConfigData; UINT32 ConfigDataSize; EFI_TIME BootTime; ConfigData = OcStorageReadFileUnicode ( Storage, OPEN_CORE_CONFIG_PATH, &ConfigDataSize ); if (ConfigData != NULL) { DEBUG ((DEBUG_INFO, "OC: Loaded configuration of %u bytes\n", ConfigDataSize)); Status = OcConfigurationInit (Config, ConfigData, ConfigDataSize); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "OC: Failed to parse configuration!\n")); CpuDeadLoop (); return EFI_UNSUPPORTED; ///< Should be unreachable. } FreePool (ConfigData); } else { DEBUG ((DEBUG_ERROR, "OC: Failed to load configuration!\n")); CpuDeadLoop (); return EFI_UNSUPPORTED; ///< Should be unreachable. } // // Sanity check that the configuration is adequate. // if (!Storage->HasVault && Config->Misc.Security.RequireVault) { DEBUG ((DEBUG_ERROR, "OC: Configuration requires vault but no vault provided!\n")); CpuDeadLoop (); return EFI_SECURITY_VIOLATION; ///< Should be unreachable. } if (VaultKey == NULL && Config->Misc.Security.RequireSignature) { DEBUG ((DEBUG_ERROR, "OC: Configuration requires signed vault but no public key provided!\n")); CpuDeadLoop (); return EFI_SECURITY_VIOLATION; ///< Should be unreachable. } if (Config->Misc.Debug.DisableWatchDog) { // // boot.efi kills watchdog only in FV2 UI. // gBS->SetWatchdogTimer (0, 0, 0, NULL); } OcConfigureLogProtocol ( Config->Misc.Debug.Target, Config->Misc.Debug.DisplayDelay, (UINTN) Config->Misc.Debug.DisplayLevel, (UINTN) Config->Misc.Security.HaltLevel, OPEN_CORE_LOG_PREFIX_PATH, Storage->FileSystem ); DEBUG (( DEBUG_INFO, "OC: OpenCore is now loading (Vault: %d/%d, Sign %d/%d)...\n", Storage->HasVault, Config->Misc.Security.RequireVault, VaultKey != NULL, Config->Misc.Security.RequireSignature )); Status = gRT->GetTime (&BootTime, NULL); if (!EFI_ERROR (Status)) { DEBUG (( DEBUG_INFO, "OC: Boot timestamp - %04u.%02u.%02u %02u:%02u:%02u\n", BootTime.Year, BootTime.Month, BootTime.Day, BootTime.Hour, BootTime.Minute, BootTime.Second )); } else { DEBUG (( DEBUG_INFO, "OC: Boot timestamp - %r\n", Status )); } return EFI_SUCCESS; } EFI_STATUS OcMiscLateInit ( IN OC_GLOBAL_CONFIG *Config, IN EFI_DEVICE_PATH_PROTOCOL *LoadPath OPTIONAL, OUT EFI_HANDLE *LoadHandle OPTIONAL ) { EFI_STATUS Status; EFI_STATUS HibernateStatus; UINT32 Width; UINT32 Height; UINT32 Bpp; BOOLEAN SetMax; CONST CHAR8 *HibernateMode; UINT32 HibernateMask; if ((Config->Misc.Security.ExposeSensitiveData & OCS_EXPOSE_BOOT_PATH) != 0) { OcStoreLoadPath (LoadPath); } Status = EFI_SUCCESS; if (LoadHandle != NULL) { *LoadHandle = NULL; // // Do not disclose self entry unless asked. // if (LoadPath != NULL && Config->Misc.Boot.HideSelf) { Status = gBS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &LoadPath, LoadHandle ); DEBUG ((DEBUG_INFO, "OC: LoadHandle is %p - %r\n", *LoadHandle, Status)); } } ParseScreenResolution ( OC_BLOB_GET (&Config->Misc.Boot.Resolution), &Width, &Height, &Bpp, &SetMax ); DEBUG (( DEBUG_INFO, "OC: Requested resolution is %ux%u@%u (max: %d) from %a\n", Width, Height, Bpp, SetMax, OC_BLOB_GET (&Config->Misc.Boot.Resolution) )); if (SetMax || (Width > 0 && Height > 0)) { Status = SetConsoleResolution (Width, Height, Bpp); DEBUG (( EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO, "OC: Changed resolution to %ux%u@%u (max: %d) from %a - %r\n", Width, Height, Bpp, SetMax, OC_BLOB_GET (&Config->Misc.Boot.Resolution), Status )); } ParseConsoleMode ( OC_BLOB_GET (&Config->Misc.Boot.ConsoleMode), &Width, &Height, &SetMax ); DEBUG (( DEBUG_INFO, "OC: Requested console mode is %ux%u (max: %d) from %a\n", Width, Height, SetMax, OC_BLOB_GET (&Config->Misc.Boot.ConsoleMode) )); if (SetMax || (Width > 0 && Height > 0)) { Status = SetConsoleMode (Width, Height); DEBUG (( EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO, "OC: Changed console mode to %ux%u (max: %d) from %a - %r\n", Width, Height, SetMax, OC_BLOB_GET (&Config->Misc.Boot.ConsoleMode), Status )); } HibernateMode = OC_BLOB_GET (&Config->Misc.Boot.HibernateMode); if (AsciiStrCmp (HibernateMode, "None") == 0) { HibernateMask = HIBERNATE_MODE_NONE; } else if (AsciiStrCmp (HibernateMode, "Auto") == 0) { HibernateMask = HIBERNATE_MODE_RTC | HIBERNATE_MODE_NVRAM; } else if (AsciiStrCmp (HibernateMode, "RTC") == 0) { HibernateMask = HIBERNATE_MODE_RTC; } else if (AsciiStrCmp (HibernateMode, "NVRAM") == 0) { HibernateMask = HIBERNATE_MODE_NVRAM; } else { DEBUG ((DEBUG_INFO, "OC: Invalid HibernateMode: %a\n", HibernateMode)); HibernateMask = HIBERNATE_MODE_NONE; } DEBUG ((DEBUG_INFO, "OC: Translated HibernateMode %a to %u\n", HibernateMode, HibernateMask)); HibernateStatus = OcActivateHibernateWake (HibernateMask); DEBUG ((DEBUG_INFO, "OC: Hibernation detection status is %r\n", HibernateStatus)); (VOID) HibernateStatus; return Status; } VOID OcMiscBoot ( IN OC_STORAGE_CONTEXT *Storage, IN OC_GLOBAL_CONFIG *Config, IN OC_IMAGE_START StartImage, IN BOOLEAN CustomBootGuid, IN EFI_HANDLE LoadHandle OPTIONAL ) { EFI_STATUS Status; OC_PICKER_CONTEXT *Context; UINTN ContextSize; UINT32 Index; UINT32 ToolIndex; OC_INTERFACE_PROTOCOL *Interface; // // Do not use our boot picker unless asked. // if (!Config->Misc.Boot.UsePicker) { DEBUG ((DEBUG_INFO, "OC: Handing off to external boot controller\n")); Status = gBS->LocateProtocol ( &gOcInterfaceProtocolGuid, NULL, (VOID **) &Interface ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OC: Missing external GUI protocol - %r\n", Status)); return; } if (Interface->Revision != OC_INTERFACE_REVISION) { DEBUG (( DEBUG_INFO, "OC: Incompatible external GUI protocol - %u vs %u\n", Interface->Revision, OC_INTERFACE_REVISION )); return; } } else { Interface = NULL; } if (!OcOverflowMulAddUN ( sizeof (OC_PICKER_ENTRY), Config->Misc.Tools.Count, sizeof (OC_PICKER_CONTEXT), &ContextSize)) { Context = AllocateZeroPool (ContextSize); } else { Context = NULL; } if (Context == NULL) { DEBUG ((DEBUG_ERROR, "OC: Failed to allocate boot picker context!\n")); return; } Context->ScanPolicy = Config->Misc.Security.ScanPolicy; Context->LoadPolicy = OC_LOAD_DEFAULT_POLICY; Context->TimeoutSeconds = Config->Misc.Boot.Timeout; Context->StartImage = StartImage; Context->ShowPicker = Config->Misc.Boot.ShowPicker; Context->CustomBootGuid = CustomBootGuid; Context->ExcludeHandle = LoadHandle; Context->CustomEntryContext = Storage; Context->CustomRead = OcToolLoadEntry; for (Index = 0, ToolIndex = 0; Index < Config->Misc.Tools.Count; ++Index) { if (Config->Misc.Tools.Values[Index]->Enabled) { Context->CustomEntries[ToolIndex].Name = OC_BLOB_GET (&Config->Misc.Tools.Values[Index]->Name); Context->CustomEntries[ToolIndex].Path = OC_BLOB_GET (&Config->Misc.Tools.Values[Index]->Path); ++ToolIndex; } } Context->CustomEntryCount = ToolIndex; if (Interface != NULL) { Status = Interface->ShowInteface (Interface, Storage, Context); } else { Status = OcRunSimpleBootPicker (Context); } if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "OC: Failed to show boot menu!\n")); } } VOID OcMiscUefiQuirksLoaded ( IN OC_GLOBAL_CONFIG *Config ) { if (((Config->Misc.Security.ScanPolicy & OC_SCAN_FILE_SYSTEM_LOCK) == 0 && (Config->Misc.Security.ScanPolicy & OC_SCAN_FILE_SYSTEM_BITS) != 0) || ((Config->Misc.Security.ScanPolicy & OC_SCAN_DEVICE_LOCK) == 0 && (Config->Misc.Security.ScanPolicy & OC_SCAN_DEVICE_BITS) != 0)) { DEBUG ((DEBUG_ERROR, "OC: Invalid ScanPolicy %X\n", Config->Misc.Security.ScanPolicy)); CpuDeadLoop (); } // // Inform drivers about our scan policy. // gRT->SetVariable ( OC_SCAN_POLICY_VARIABLE_NAME, &gOcVendorVariableGuid, OPEN_CORE_INT_NVRAM_ATTR, sizeof (Config->Misc.Security.ScanPolicy), &Config->Misc.Security.ScanPolicy ); OcConsoleControlSetBehaviour ( ParseConsoleControlBehaviour ( OC_BLOB_GET (&Config->Misc.Boot.ConsoleBehaviourUi) ) ); }