/* * Copyright (C) 2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ /* Slice 2011, some more adoptations for Apple's OS */ /******************************************************************************* * Header Files * *******************************************************************************/ #include // Only use angled for Platform, else, xcode project won't compile #include //#include #include "Injectors.h" //#include "../include/SmcHelper.h" #include "../Platform/Settings.h" #include #include #include #include extern "C" { #include "../../Protocols/AppleKeyAggregator/AppleKeyAggregator.h" } #ifndef DEBUG_ALL #define DEBUG_PRO 1 #else #define DEBUG_PRO DEBUG_ALL #endif #if DEBUG_PRO == 0 #define DBG(...) #else #define DBG(...) DebugLog(DEBUG_PRO, __VA_ARGS__) #endif UINT32 mPropSize = 0; UINT8* mProperties = NULL; CHAR8* gDeviceProperties = NULL; UINT32 cPropSize = 0; UINT8* cProperties = NULL; //this is properties as string CHAR8* BootOSName = NULL; UINT16 KeyboardVendor = 0x05ac; //Apple inc. UINT16 KeyboardProduct = 0x021d; //iMac aluminium extern UINT32 mCurrentColor; extern EFI_GUID gAppleUserInterfaceThemeProtocolGuid; extern EFI_GUID gAppleSystemInfoProtocolGuid; extern APPLE_IMAGE_CODEC_PROTOCOL gAppleImageCodec; typedef struct _APPLE_GETVAR_PROTOCOL APPLE_GETVAR_PROTOCOL; // GET_PROPERTY_VALUE /** Locates a device property in the database and returns its value into Value. @param[in] This A pointer to the protocol instance. @param[in] DevicePath The device path of the device to get the property of. @param[in] Name The Name of the requested property. @param[out] Value The Buffer allocated by the caller to return the value of the property into. @param[in, out] Size On input the size of the allocated Value Buffer. On output the size required to fill the Buffer. @return The status of the operation is returned. @retval EFI_BUFFER_TOO_SMALL The memory required to return the value exceeds the size of the allocated Buffer. The required size to complete the operation has been returned into Size. @retval EFI_NOT_FOUND The given device path does not have a property with the specified Name. @retval EFI_SUCCESS The operation completed successfully. **/ typedef EFI_STATUS (EFIAPI *APPLE_GETVAR_PROTOCOL_GET_PROPERTY_VALUE) ( IN APPLE_GETVAR_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *Name, OUT void *Value, OPTIONAL IN OUT UINTN *Size ); // SET_PROPERTY /** Sets the specified property of the given device path to the provided Value. @param[in] This A pointer to the protocol instance. @param[in] DevicePath The device path of the device to set the property of. @param[in] Name The Name of the desired property. @param[in] Value The Buffer holding the value to set the property to. @param[out] Size The size of the Value Buffer. @return The status of the operation is returned. @retval EFI_OUT_OF_RESOURCES The memory necessary to complete the operation could not be allocated. @retval EFI_SUCCESS The operation completed successfully. **/ typedef EFI_STATUS (EFIAPI *APPLE_GETVAR_PROTOCOL_SET_PROPERTY) ( IN APPLE_GETVAR_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *Name, IN void *Value, IN UINTN Size ); // REMOVE_PROPERTY /** Removes the specified property from the given device path. @param[in] This A pointer to the protocol instance. @param[in] DevicePath The device path of the device to set the property of. @param[in] Name The Name of the desired property. @return The status of the operation is returned. @retval EFI_NOT_FOUND The given device path does not have a property with the specified Name. @retval EFI_SUCCESS The operation completed successfully. **/ typedef EFI_STATUS (EFIAPI *APPLE_GETVAR_PROTOCOL_REMOVE_PROPERTY) ( IN APPLE_GETVAR_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *Name ); typedef EFI_STATUS (EFIAPI *APPLE_GETVAR_PROTOCOL_GET_DEVICE_PROPS) ( IN APPLE_GETVAR_PROTOCOL *This, IN CHAR8 *Buffer, IN OUT UINT32 *BufferSize); struct _APPLE_GETVAR_PROTOCOL { UINT64 Sign; APPLE_GETVAR_PROTOCOL_GET_PROPERTY_VALUE GetPropertyValue; //8 APPLE_GETVAR_PROTOCOL_SET_PROPERTY SetProperty; //0x10 APPLE_GETVAR_PROTOCOL_REMOVE_PROPERTY RemoveProperty; //0x18 APPLE_GETVAR_PROTOCOL_GET_DEVICE_PROPS GetPropertyBuffer;//0x20 }; #define DEVICE_PROPERTIES_SIGNATURE SIGNATURE_64('A','P','P','L','E','D','E','V') EFI_STATUS EFIAPI GetDeviceProps(IN APPLE_GETVAR_PROTOCOL *This, IN CHAR8 *Buffer, IN OUT UINT32 *BufferSize) { if(!gSettings.Devices.StringInjector && (mProperties != NULL) && (mPropSize > 1)) { if (*BufferSize < mPropSize) { *BufferSize = mPropSize; return EFI_BUFFER_TOO_SMALL; } *BufferSize = mPropSize; CopyMem(Buffer, mProperties, mPropSize); return EFI_SUCCESS; } else if ((cProperties != NULL) && (cPropSize > 1)) { if (*BufferSize < cPropSize) { *BufferSize = cPropSize; return EFI_BUFFER_TOO_SMALL; } *BufferSize = cPropSize; CopyMem(Buffer, cProperties, cPropSize); return EFI_SUCCESS; } *BufferSize = 0; return EFI_SUCCESS; } APPLE_GETVAR_PROTOCOL mDeviceProperties= { DEVICE_PROPERTIES_SIGNATURE, NULL, NULL, NULL, GetDeviceProps }; typedef EFI_STATUS (EFIAPI *EFI_SCREEN_INFO_FUNCTION)( void* This, UINT64* baseAddress, UINT64* frameBufferSize, UINT32* byterPerRow, UINT32* Width, UINT32* Height, UINT32* colorDepth ); typedef struct { EFI_SCREEN_INFO_FUNCTION GetScreenInfo; } EFI_INTERFACE_SCREEN_INFO; EFI_STATUS EFIAPI GetScreenInfo(void* This, UINT64* baseAddress, UINT64* frameBufferSize, UINT32* bpr, UINT32* w, UINT32* h, UINT32* colorDepth) { /* * This implementation has no sense * as this protocol will be called only if GOP is absent. Somehow as a replacement * There will be a sense to find bootargs->frame_address * and fill other values * but we always have GOP ;) */ EFI_GRAPHICS_OUTPUT_PROTOCOL *mGraphicsOutput=NULL; EFI_STATUS Status; Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (void **) &mGraphicsOutput); if(EFI_ERROR(Status)) return EFI_UNSUPPORTED; //this print never occured so this procedure is redundant DBG("GetScreenInfo called\n"); // printf("GetScreenInfo called with args: %lx %lx %lx %lx %lx %lx\n", // baseAddress, frameBufferSize, bpr, w, h, colorDepth); *frameBufferSize = (UINT64)mGraphicsOutput->Mode->FrameBufferSize; *baseAddress = (UINT64)mGraphicsOutput->Mode->FrameBufferBase; *w = (UINT32)mGraphicsOutput->Mode->Info->HorizontalResolution; *h = (UINT32)mGraphicsOutput->Mode->Info->VerticalResolution; *colorDepth = 32; *bpr = (UINT32)(mGraphicsOutput->Mode->Info->PixelsPerScanLine*32) >> 3; // printf(" Screen info: FBsize=%lx FBaddr=%lx w=%d h=%d\n", // *frameBufferSize, *baseAddress, *w, *h); // PauseForKey(L"--- press any key ---\n"); return EFI_SUCCESS; } EFI_INTERFACE_SCREEN_INFO mScreenInfo= { GetScreenInfo }; //#define EFI_OS_INFO_PROTOCOL_REVISION 0x01 // OpenCore define this to 03 // OS_INFO_VENDOR_NAME #define OS_INFO_VENDOR_NAME "Apple Inc." // OSInfoOSNameImpl void EFIAPI OSInfoOSNameImpl ( OUT CHAR8 *OSName ) { // for future developers // this variable can be used at OnExitBoootServices, // as it will be set by boot.efi BootOSName = (__typeof__(BootOSName))AllocateCopyPool(AsciiStrLen(OSName) + 1, (void*)OSName); DBG("OSInfo:OSName called. OSName=%s\n", OSName); EfiNamedEventSignal(gAppleOSLoadedNamedEventGuid); } // OSInfoOSVendorImpl void EFIAPI OSInfoOSVendorImpl ( IN CHAR8 *OSVendor ) { // never used as never called INTN Result; DBG("OSInfo:OSVendor called\n"); if (!OSVendor) { return; } Result = AsciiStrCmp(OSVendor, OS_INFO_VENDOR_NAME); if (Result == 0) { // EfiLibNamedEventSignal (&gAppleOSLoadedNamedEventGuid); } } EFI_OS_INFO_PROTOCOL mEfiOSInfo = { EFI_OS_INFO_PROTOCOL_REVISION, OSInfoOSNameImpl, OSInfoOSVendorImpl, NULL, NULL }; //Usage /*RestoreConfig(This, 2, 400, R, G, B) ->LocateProtocol(gAppleGraphConfigProtocolGuid, 0, 78000000438/1F7DAEC8) = Success call sub_30150 ->GetVariable(boot-gamma, gEfiAppleBootGuid, 0/50, 0, 0) = Not Found mRestored = true; ->GraphConfig.RestoreConfig(2, 400, 1FFCE8B0, 1FFCE0B0, 1FFCD8B0) status=Success */ EFI_STATUS EFIAPI RestoreConfig (APPLE_GRAPH_CONFIG_PROTOCOL* This, UINT32 Param1, UINT32 Param2, void* Param3, void* Param4, void* Param5 ) { DBG("RestoreConfig called Param1=%x\n", Param1); return EFI_SUCCESS; } APPLE_GRAPH_CONFIG_PROTOCOL mGraphConfig = { 1, RestoreConfig, }; EFI_STATUS EFIAPI UsbKbGetKeyboardDeviceInfo ( OUT UINT16 *IdVendor, OUT UINT16 *IdProduct, OUT UINT8 *CountryCode ) { if (IdVendor) { *IdVendor = KeyboardVendor; } if (IdProduct) { *IdProduct = KeyboardProduct; } if (CountryCode) { *CountryCode = 0; } DBG("KeyboardDeviceInfo called\n"); return EFI_SUCCESS; } EFI_KEYBOARD_INFO_PROTOCOL mKeyboardInfo = { UsbKbGetKeyboardDeviceInfo }; extern EFI_GUID gAppleUserInterfaceThemeProtocolGuid; typedef EFI_STATUS (EFIAPI *APPLE_USER_INTERFACE_THEME_GETCOLOR) ( IN OUT UINT32 * Color ); typedef struct { UINT64 Version; APPLE_USER_INTERFACE_THEME_GETCOLOR GetColor; } APPLE_USER_INTERFACE_THEME_PROTOCOL; EFI_STATUS EFIAPI UserInterfaceThemeGetColor ( UINT32 *Color ) { if (Color == NULL) { return EFI_INVALID_PARAMETER; } *Color = mCurrentColor; return EFI_SUCCESS; } STATIC APPLE_USER_INTERFACE_THEME_PROTOCOL mAppleUserInterfaceThemeProtocol = { 1, UserInterfaceThemeGetColor }; BOOLEAN EFIAPI IsGibraltar () { return FALSE; } APPLE_SYSTEM_INFO_PROTOCOL mSystemInfo = { 1, IsGibraltar }; extern EFI_FIRMWARE_VOLUME_PROTOCOL FirmwareVolume; extern APPLE_SMC_IO_PROTOCOL SMCHelperProtocol; extern APPLE_SMC_STATE_PROTOCOL SMCStateProtocol; EFI_STATUS SetPrivateVarProto(void) { EFI_STATUS Status; //This must be independent install // optional protocols Status = gBS->InstallMultipleProtocolInterfaces (&gImageHandle, &gAppleFramebufferInfoProtocolGuid, &mScreenInfo, // &gEfiOSInfoProtocolGuid, // &mEfiOSInfo, &gAppleGraphConfigProtocolGuid, &mGraphConfig, &gEfiKeyboardInfoProtocolGuid, &mKeyboardInfo, &gAppleUserInterfaceThemeProtocolGuid, &mAppleUserInterfaceThemeProtocol, &gEfiFirmwareVolumeProtocolGuid, &FirmwareVolume, &gAppleSMCProtocolGuid, &SMCHelperProtocol, &gAppleSMCStateProtocolGuid, &SMCStateProtocol, NULL ); if (EFI_ERROR(Status)) { DBG("Error installing multiple protocol, Status = %s\n", efiStrError(Status)); } Status = gBS->InstallProtocolInterface ( &gImageHandle, &gAppleImageCodecProtocolGuid, EFI_NATIVE_INTERFACE, (VOID *)&gAppleImageCodec ); if (EFI_ERROR(Status)) { DBG("AppleImageCodec: error installing protocol, Status = %s\n", efiStrError(Status)); } Status = InstallAggregator(); if (EFI_ERROR(Status)) { DBG("AppleKeyAggregator: error installing protocol, Status = %s\n", efiStrError(Status)); } //obligatory protocol Status = gBS->InstallProtocolInterface (&gImageHandle, &gEfiDevicePathPropertyDatabaseProtocolGuid, EFI_NATIVE_INTERFACE, &mDeviceProperties ); if (EFI_ERROR(Status)) { DBG("DevicePathPropertyDatabase: error installing protocol, Status = %s\n", efiStrError(Status)); } return Status; }