VirtualBox

Ignore:
Timestamp:
Sep 27, 2019 8:53:09 PM (5 years ago)
Author:
vboxsync
Message:

iprt/system: Fixing the firmware stuff a little.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/RTSystemFirmware-win.cpp

    r80860 r81062  
    2929*   Header Files                                                                                                                 *
    3030*********************************************************************************************************************************/
     31#include "internal/iprt.h"
     32#include <iprt/system.h>
    3133
    3234#include <iprt/nt/nt-and-windows.h>
    33 
     35#include <WinSDKVer.h>
     36
     37#include <iprt/asm.h>
    3438#include <iprt/assert.h>
    35 #include <iprt/errcore.h>
     39#include <iprt/err.h>
    3640#include <iprt/mem.h>
    3741#include <iprt/ldr.h>
    3842#include <iprt/string.h>
    39 #include <iprt/system.h>
    4043#include <iprt/utf16.h>
    4144
     45#include "internal-r3-win.h"
     46
    4247
    4348/*********************************************************************************************************************************
    4449*   Structures and Typedefs                                                                                                      *
    4550*********************************************************************************************************************************/
    46 /**
    47  * These are the FirmwareType* defines found in the Vista Platform SDK and returned
    48  * by GetProductInfo().
    49  *
    50  * We define them ourselves because we don't necessarily have any Vista PSDK around.
    51  */
    52 typedef enum RTWINFWTYPE
    53 {
    54     kRTWinFirmwareTypeUnknown = 0,
    55     kRTWinFirmwareTypeBios    = 1,
    56     kRTWinFirmwareTypeUefi    = 2,
    57     kRTWinFirmwareTypeMax     = 3
    58 } RTWINFWTYPE;
    59 
    60 /** Function pointer for dynamic import of GetFirmwareType(). */
    61 typedef BOOL (WINAPI *PFNGETFIRMWARETYPE)(RTWINFWTYPE *);
    62 
     51#if _WIN32_MAXVER < 0x0602 /* Windows 7 or older, supply missing GetFirmwareType bits. */
     52typedef enum _FIRMWARE_TYPE
     53{
     54    FirmwareTypeUnknown,
     55    FirmwareTypeBios,
     56    FirmwareTypeUefi,
     57    FirmwareTypeMax
     58} FIRMWARE_TYPE;
     59typedef FIRMWARE_TYPE *PFIRMWARE_TYPE;
     60WINBASEAPI BOOL WINAPI GetFirmwareType(PFIRMWARE_TYPE);
     61#endif
     62
     63
     64/*********************************************************************************************************************************
     65*   Defined Constants And Macros                                                                                                 *
     66*********************************************************************************************************************************/
    6367/** Defines the UEFI Globals UUID. */
    6468#define VBOX_UEFI_UUID_GLOBALS L"{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}"
    6569/** Defines an UEFI dummy UUID. */
    6670#define VBOX_UEFI_UUID_DUMMY   L"{00000000-0000-0000-0000-000000000000}"
     71
     72
     73/*********************************************************************************************************************************
     74*   Global Variables                                                                                                             *
     75*********************************************************************************************************************************/
     76static volatile bool                              g_fResolvedApis = false;
     77static decltype(GetFirmwareType)                 *g_pfnGetFirmwareType;
     78static decltype(GetFirmwareEnvironmentVariableW) *g_pfnGetFirmwareEnvironmentVariableW;
     79
     80
     81static void rtSystemFirmwareResolveApis(void)
     82{
     83    FARPROC pfnTmp1 = GetProcAddress(g_hModKernel32, "GetFirmwareType");
     84    FARPROC pfnTmp2 = GetProcAddress(g_hModKernel32, "GetFirmwareEnvironmentVariableW");
     85    ASMCompilerBarrier(); /* paranoia^2 */
     86
     87    g_pfnGetFirmwareType                 = (decltype(GetFirmwareType) *)pfnTmp1;
     88    g_pfnGetFirmwareEnvironmentVariableW = (decltype(GetFirmwareEnvironmentVariableW) *)pfnTmp2;
     89    ASMAtomicWriteBool(&g_fResolvedApis, true);
     90}
    6791
    6892
     
    95119
    96120
    97 RTDECL(int) RTSystemFirmwareQueryType(PRTSYSFWTYPE pFirmwareType)
    98 {
    99     AssertPtrReturn(pFirmwareType, VERR_INVALID_POINTER);
    100 
    101     RTSYSFWTYPE fwType = RTSYSFWTYPE_UNKNOWN;
    102 
    103     RTLDRMOD hKernel32 = NIL_RTLDRMOD;
    104     int rc = RTLdrLoadSystem("Kernel32.dll", /* fNoUnload = */ true, &hKernel32);
    105     if (RT_SUCCESS(rc))
    106     {
    107         PFNGETFIRMWARETYPE pfnGetFirmwareType;
    108         rc = RTLdrGetSymbol(hKernel32, "GetFirmwareType", (void **)&pfnGetFirmwareType); /* Only >= Windows 8. */
    109         if (RT_SUCCESS(rc))
    110         {
    111             RTWINFWTYPE winFwType;
    112             if (pfnGetFirmwareType(&winFwType))
     121RTDECL(int) RTSystemFirmwareQueryType(PRTSYSFWTYPE penmFirmwareType)
     122{
     123    AssertPtrReturn(penmFirmwareType, VERR_INVALID_POINTER);
     124
     125    if (!g_fResolvedApis)
     126        rtSystemFirmwareResolveApis();
     127
     128    *penmFirmwareType = RTSYSFWTYPE_INVALID;
     129    int rc = VERR_NOT_SUPPORTED;
     130
     131    /* GetFirmwareType is Windows 8 and later. */
     132    if (g_pfnGetFirmwareType)
     133    {
     134        FIRMWARE_TYPE enmWinFwType;
     135        if (g_pfnGetFirmwareType(&enmWinFwType))
     136        {
     137            switch (enmWinFwType)
    113138            {
    114                 switch (winFwType)
    115                 {
    116                     case kRTWinFirmwareTypeBios:
    117                         fwType = RTSYSFWTYPE_BIOS;
    118                         break;
    119 
    120                     case kRTWinFirmwareTypeUefi:
    121                         fwType = RTSYSFWTYPE_UEFI;
    122                         break;
    123 
    124                     default: /* Huh? */
    125                         fwType = RTSYSFWTYPE_UNKNOWN;
    126                         break;
    127                 }
     139                case FirmwareTypeBios:
     140                    *penmFirmwareType = RTSYSFWTYPE_BIOS;
     141                    break;
     142                case FirmwareTypeUefi:
     143                    *penmFirmwareType = RTSYSFWTYPE_UEFI;
     144                    break;
     145                default:
     146                    *penmFirmwareType = RTSYSFWTYPE_UNKNOWN;
     147                    AssertMsgFailed(("%d\n", enmWinFwType));
     148                    break;
     149            }
     150            rc = VINF_SUCCESS;
     151        }
     152        else
     153            rc = RTErrConvertFromWin32(GetLastError());
     154    }
     155    /* GetFirmwareEnvironmentVariableW is XP and later. */
     156    else if (g_pfnGetFirmwareEnvironmentVariableW)
     157    {
     158        rtSystemFirmwareGetPrivileges(SE_SYSTEM_ENVIRONMENT_NAME);
     159
     160        uint8_t fEnabled = 0; /** @todo This type doesn't make sense to bird. */
     161        DWORD cbRet = g_pfnGetFirmwareEnvironmentVariableW(L"", VBOX_UEFI_UUID_GLOBALS, &fEnabled, sizeof(fEnabled));
     162        if (cbRet)
     163        {
     164            Assert(cbRet == sizeof(fEnabled));
     165            *penmFirmwareType = fEnabled ? RTSYSFWTYPE_UEFI : RTSYSFWTYPE_BIOS;
     166            rc = VINF_SUCCESS;
     167        }
     168        else
     169        {
     170            DWORD dwErr = GetLastError();
     171            if (dwErr == ERROR_INVALID_FUNCTION)
     172            {
     173                *penmFirmwareType = RTSYSFWTYPE_BIOS;
     174                rc = VINF_SUCCESS;
    128175            }
    129176            else
    130                 rc = RTErrConvertFromWin32(GetLastError());
    131         }
    132         else /* Fallback for OSes < Windows 8. */
    133         {
    134             rc = rtSystemFirmwareGetPrivileges(SE_SYSTEM_ENVIRONMENT_NAME);
    135             if (RT_SUCCESS(rc))
    136             {
    137                 PCWCHAR pcwszGUID = VBOX_UEFI_UUID_GLOBALS; /* UEFI Globals. */
    138                 PCWCHAR pcwszName = L"";
    139 
    140                 uint8_t uEnabled = 0;
    141                 DWORD dwRet = GetFirmwareEnvironmentVariableW(pcwszName, pcwszGUID, &uEnabled, sizeof(uEnabled));
    142                 if (dwRet) /* Returns the bytes written. */
    143                 {
    144                     Assert(dwRet == sizeof(uEnabled));
    145                     fwType = RT_BOOL(uEnabled) ? RTSYSFWTYPE_UEFI : RTSYSFWTYPE_BIOS;
    146                 }
    147                 else
    148                     rc = RTErrConvertFromWin32(GetLastError());
    149             }
    150         }
    151 
    152         RTLdrClose(hKernel32);
    153     }
    154 
    155     if (RT_SUCCESS(rc))
    156         *pFirmwareType = fwType;
    157 
     177                rc = RTErrConvertFromWin32(dwErr);
     178        }
     179    }
    158180    return rc;
    159181}
    160182
    161183
    162 RTDECL(void) RTSystemFirmwareValueFree(PRTSYSFWVALUE pValue)
    163 {
    164     if (!pValue)
    165         return;
    166 
    167     /** @todo Implement cleanup here. */
    168 }
    169 
    170 
    171 RTDECL(int) RTSystemFirmwareValueQuery(RTSYSFWPROP enmProp, PRTSYSFWVALUE *ppValue)
    172 {
    173     int rc = rtSystemFirmwareGetPrivileges(SE_SYSTEM_ENVIRONMENT_NAME);
    174     if (RT_FAILURE(rc))
    175         return rc;
    176 
    177     PRTSYSFWVALUE pValue = (PRTSYSFWVALUE)RTMemAlloc(sizeof(RTSYSFWVALUE));
    178     if (!pValue)
    179         return VERR_NO_MEMORY;
    180 
    181     char *pszName = NULL;
    182     DWORD dwSize  = 0;
    183 
     184RTDECL(void) RTSystemFirmwareFreeValue(PRTSYSFWVALUE pValue)
     185{
     186    RT_NOREF(pValue);
     187}
     188
     189
     190RTDECL(int) RTSystemFirmwareQueryValue(RTSYSFWPROP enmProp, PRTSYSFWVALUE pValue)
     191{
     192    RT_ZERO(*pValue);
     193
     194    /*
     195     * Translate the enmProp to a name and type:
     196     */
     197    const wchar_t *pwszName = NULL;
    184198    switch (enmProp)
    185199    {
    186200        case RTSYSFWPROP_SECURE_BOOT:
    187201        {
    188             rc = RTStrAAppend(&pszName, "SecureBoot");
    189             if (RT_FAILURE(rc))
    190                 break;
    191 
     202            pwszName = L"SecureBoot";
    192203            pValue->enmType = RTSYSFWVALUETYPE_BOOLEAN;
    193             dwSize = 1;
    194204            break;
    195205        }
    196206
    197         case RTSYSFWPROP_BOOT_CURRENT:
    198             RT_FALL_THROUGH();
    199         case RTSYSFWPROP_BOOT_ORDER:
    200             RT_FALL_THROUGH();
    201         case RTSYSFWPROP_BOOT_NEXT:
    202             RT_FALL_THROUGH();
    203         case RTSYSFWPROP_TIMEOUT:
    204             RT_FALL_THROUGH();
    205         case RTSYSFWPROP_PLATFORM_LANG:
    206             rc = VERR_NOT_IMPLEMENTED;
     207        default:
     208            AssertReturn(enmProp > RTSYSFWPROP_INVALID && enmProp < RTSYSFWPROP_END, VERR_INVALID_PARAMETER);
     209            return VERR_SYS_UNSUPPORTED_FIRMWARE_PROPERTY;
     210    }
     211
     212    if (!g_pfnGetFirmwareEnvironmentVariableW)
     213        return VERR_NOT_SUPPORTED;
     214    rtSystemFirmwareGetPrivileges(SE_SYSTEM_ENVIRONMENT_NAME);
     215
     216    int rc;
     217    switch (pValue->enmType)
     218    {
     219        case RTSYSFWVALUETYPE_BOOLEAN:
     220        {
     221            uint8_t bValue = 0;
     222            DWORD cbRet = g_pfnGetFirmwareEnvironmentVariableW(pwszName, VBOX_UEFI_UUID_GLOBALS, &bValue, sizeof(bValue));
     223            pValue->u.fVal = cbRet != 0 && bValue != 0;
     224            rc = cbRet != 0 || GetLastError() == ERROR_INVALID_FUNCTION ? VINF_SUCCESS : RTErrConvertFromWin32(GetLastError());
    207225            break;
     226        }
    208227
    209228        default:
    210             rc = VERR_INVALID_PARAMETER;
    211             break;
    212     }
    213 
    214     if (RT_SUCCESS(rc))
    215     {
    216         PRTUTF16 pwszName;
    217         rc = RTStrToUtf16(pszName, &pwszName);
    218         if (RT_SUCCESS(rc))
    219         {
    220             void *pvBuf = RTMemAlloc(dwSize);
    221             DWORD dwBuf = dwSize;
    222 
    223             if (pvBuf)
    224             {
    225                 DWORD dwRet = GetFirmwareEnvironmentVariableW(pwszName, VBOX_UEFI_UUID_GLOBALS, pvBuf, dwBuf);
    226                 if (dwRet)
    227                 {
    228                     switch (pValue->enmType)
    229                     {
    230                         case RTSYSFWVALUETYPE_BOOLEAN:
    231                             pValue->u.fVal = RT_BOOL(*(uint8_t *)pvBuf);
    232                             break;
    233 
    234                         case RTSYSFWVALUETYPE_INVALID:
    235                             RT_FALL_THROUGH();
    236                         default:
    237                             AssertFailed();
    238                             break;
    239                     }
    240                 }
    241                 else
    242                     rc = RTErrConvertFromWin32(GetLastError());
    243 
    244                 RTMemFree(pvBuf);
    245             }
    246             else
    247                 rc = VERR_NO_MEMORY;
    248 
    249             RTUtf16Free(pwszName);
    250         }
    251     }
    252 
    253     RTStrFree(pszName);
    254 
    255     if (RT_SUCCESS(rc))
    256     {
    257         *ppValue = pValue;
    258     }
    259     else
    260         RTSystemFirmwareValueFree(pValue);
     229            AssertFailedReturn(VERR_INTERNAL_ERROR);
     230    }
    261231
    262232    return rc;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette