ToggleSipEntry.c 7.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/** @file
  Boot entry protocol implementation of Toggle SIP boot picker entry.

  Copyright (c) 2022, Mike Beaton. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-3-Clause
**/

#include <Guid/AppleVariable.h>
#include <IndustryStandard/AppleCsrConfig.h>

#include <Uefi.h>
#include <Library/BaseLib.h>
13
#include <Library/MemoryAllocationLib.h>
14 15 16 17 18
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>

#include <Protocol/OcBootEntry.h>

19 20 21 22 23 24
#define OC_MENU_TOGGLE_SIP           "Toggle SIP (%a)"
#define OC_MENU_TOGGLE_SIP_SHOW_CSR  "Toggle SIP (0x%X:%a)"
#define OC_MENU_TOGGLE_SIP_MAX_SIZE  (\
    sizeof(OC_MENU_TOGGLE_SIP_SHOW_CSR) \
  + sizeof(UINT32) * 2 * sizeof (CHAR8) - L_STR_LEN("%X") \
  + L_STR_LEN("Disabled") - L_STR_LEN("%a"))
25

26 27 28 29
STATIC UINT32   mCsrUserConfig;
STATIC UINT32   mCsrNextConfig;
STATIC UINT32   mAttributes;
STATIC BOOLEAN  mShowCsr;
30 31 32 33 34 35 36

STATIC
EFI_STATUS
SystemActionSetSip (
  IN OUT          OC_PICKER_CONTEXT  *Context
  )
{
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
  EFI_STATUS  Status;
  BOOLEAN     IsEnabled;
  UINT32      CsrActiveConfig;

  Status = OcSetSip (&mCsrNextConfig, mAttributes);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_WARN, "BEP: OcSetSip (0x%X, 0x%X) failed! - %r\n", mCsrNextConfig, mAttributes, Status));
    return Status;
  }

  Status = OcGetSip (&CsrActiveConfig, &mAttributes);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_WARN, "BEP: OcGetSip (0x%X, 0x%X) failed! - %r\n", mCsrNextConfig, mAttributes, Status));
    return Status;
  }

  IsEnabled = OcIsSipEnabled (Status, CsrActiveConfig);

  DEBUG ((
    DEBUG_INFO,
    "BEP: SystemActionSetSip csr-active-config=0x%X (SIP %a) - %r\n",
    CsrActiveConfig,
    (IsEnabled ? "enabled" : "disabled"),
    Status
    ));

  return Status;
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
}

STATIC OC_PICKER_ENTRY  mToggleSipBootEntries[1] = {
  {
    .Id            = "toggle_sip",
    .Name          = NULL, ///< overridden in set up
    .Path          = NULL,
    .Arguments     = NULL,
    .Flavour       = NULL, ///< overridden in set up
    .Auxiliary     = TRUE,
    .Tool          = FALSE,
    .TextMode      = FALSE,
    .RealPath      = FALSE,
    .SystemAction  = SystemActionSetSip,
    .AudioBasePath = NULL, ///< overridden in set up
    .AudioBaseType = OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE
  }
};

STATIC
EFI_STATUS
EFIAPI
ToggleSipGetBootEntries (
  IN OUT          OC_PICKER_CONTEXT  *PickerContext,
  IN     CONST EFI_HANDLE            Device OPTIONAL,
  OUT       OC_PICKER_ENTRY          **Entries,
  OUT       UINTN                    *NumEntries
  )
{
  EFI_STATUS  Status;
  UINT32      CsrActiveConfig;
  BOOLEAN     IsEnabled;
96
  CHAR8       *Name;
97 98 99 100 101 102 103 104 105 106 107 108 109 110

  //
  // Custom entries only.
  //
  if (Device != NULL) {
    return EFI_NOT_FOUND;
  }

  //
  // Configure current action.
  //
  Status = OcGetSip (&CsrActiveConfig, &mAttributes);
  if (!EFI_ERROR (Status) || (Status == EFI_NOT_FOUND)) {
    IsEnabled = OcIsSipEnabled (Status, CsrActiveConfig);
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

    //
    // Same logic as in CsrUtil.efi to determine attributes to use
    // (specifically keep same V or NV setting as existing value, if any).
    //
    if (Status == EFI_NOT_FOUND) {
      //
      // TODO: We may want to upgrade Boot Entry Protocol again, so that
      // this line is able to access and respect OC WriteFlash setting?
      //
      mAttributes     = CSR_APPLE_SIP_NVRAM_NV_ATTR;
      CsrActiveConfig = 0;
    } else {
      //
      // We are finding other bits set on Apl, specifically 0x80000000,
      // so only consider relevant bits.
      //
      mAttributes &= CSR_APPLE_SIP_NVRAM_NV_ATTR;
    }
130 131 132 133 134
  } else {
    DEBUG ((DEBUG_WARN, "BEP: ToggleSip failed to read csr-active-config, aborting! - %r\n", Status));
    return Status;
  }

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
  Name = AllocatePool (OC_MENU_TOGGLE_SIP_MAX_SIZE);
  if (Name == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  if (mShowCsr) {
    Status = OcAsciiSafeSPrint (
               Name,
               OC_MENU_TOGGLE_SIP_MAX_SIZE,
               OC_MENU_TOGGLE_SIP_SHOW_CSR,
               CsrActiveConfig,
               IsEnabled ? "Enabled" : "Disabled"
               );
  } else {
    Status = OcAsciiSafeSPrint (
               Name,
               OC_MENU_TOGGLE_SIP_MAX_SIZE,
               OC_MENU_TOGGLE_SIP,
               IsEnabled ? "Enabled" : "Disabled"
               );
  }

  if (EFI_ERROR (Status)) {
    ASSERT (FALSE);
    FreePool (Name);
    return EFI_ABORTED;
  }

  mToggleSipBootEntries[0].Name = Name;
164 165 166 167 168 169 170 171 172 173
  if (IsEnabled) {
    mToggleSipBootEntries[0].Flavour       = OC_FLAVOUR_TOGGLE_SIP_ENABLED;
    mToggleSipBootEntries[0].AudioBasePath = OC_VOICE_OVER_AUDIO_FILE_SIP_IS_ENABLED;
    mCsrNextConfig                         = mCsrUserConfig;
  } else {
    mToggleSipBootEntries[0].Flavour       = OC_FLAVOUR_TOGGLE_SIP_DISABLED;
    mToggleSipBootEntries[0].AudioBasePath = OC_VOICE_OVER_AUDIO_FILE_SIP_IS_DISABLED;
    mCsrNextConfig                         = 0;
  }

174 175 176 177 178 179 180 181
  DEBUG ((
    DEBUG_INFO,
    "BEP: Toggle SIP entry, currently %a, will change 0x%X->0x%X%a\n",
    (IsEnabled ? "enabled" : "disabled"),
    CsrActiveConfig,
    mCsrNextConfig,
    ((mAttributes & EFI_VARIABLE_NON_VOLATILE) == 0 ? " (volatile)" : "")
    ));
182 183 184 185 186 187 188

  *Entries    = mToggleSipBootEntries;
  *NumEntries = ARRAY_SIZE (mToggleSipBootEntries);

  return EFI_SUCCESS;
}

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
STATIC
VOID
EFIAPI
ToggleSipFreeBootEntries (
  IN           OC_PICKER_ENTRY  **Entries,
  IN           UINTN            NumEntries
  )
{
  UINTN  Index;

  if (NumEntries == 0) {
    return;
  }

  ASSERT (NumEntries == 1);
  ASSERT (Entries != NULL);

  for (Index = 0; Index < NumEntries; Index++) {
    if (Entries[Index]->Name != NULL) {
      FreePool ((VOID *)Entries[Index]->Name);  ///< Discard const
    }
  }
}

213 214 215 216 217
STATIC
OC_BOOT_ENTRY_PROTOCOL
  mToggleSipBootEntryProtocol = {
  OC_BOOT_ENTRY_PROTOCOL_REVISION,
  ToggleSipGetBootEntries,
218
  ToggleSipFreeBootEntries
219 220 221 222 223 224 225 226 227 228 229
};

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                 Status;
  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
230 231 232
  OC_FLEX_ARRAY              *ParsedLoadOptions;
  CHAR16                     *Option;
  UINTN                      Index;
233
  UINTN                      Data;
234
  BOOLEAN                    HasUserCsr;
235 236 237 238 239 240 241 242 243 244

  Status = gBS->HandleProtocol (
                  ImageHandle,
                  &gEfiLoadedImageProtocolGuid,
                  (VOID **)&LoadedImage
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

245 246 247 248 249 250 251 252 253 254 255
  Status     = OcParseLoadOptions (LoadedImage, &ParsedLoadOptions);
  HasUserCsr = FALSE;
  if (!EFI_ERROR (Status)) {
    for (Index = 0; Index < ParsedLoadOptions->Count; Index++) {
      Option = OcParsedVarsItemAt (ParsedLoadOptions, Index)->Unicode.Name;
      if (Option[0] != L'-') {
        if (OcUnicodeStartsWith (Option, L"0x", TRUE)) {
          Status = StrHexToUintnS (Option, NULL, &Data);
        } else {
          Status = StrDecimalToUintnS (Option, NULL, &Data);
        }
256

257 258 259 260 261 262 263
        if (EFI_ERROR (Status)) {
          DEBUG ((DEBUG_WARN, "BEP: ToggleSip cannot parse %s - %r\n", Option, Status));
          HasUserCsr = FALSE;
        } else {
          HasUserCsr = TRUE;
        }
      }
264 265
    }

266 267 268 269 270 271 272 273
    mShowCsr = OcHasParsedVar (ParsedLoadOptions, L"--show-csr", OcStringFormatUnicode);

    OcFlexArrayFree (&ParsedLoadOptions);
  } else {
    ASSERT (ParsedLoadOptions == NULL);

    if (Status != EFI_NOT_FOUND) {
      return Status;
274
    }
275 276

    mShowCsr = FALSE;
277 278
  }

279
  if (HasUserCsr) {
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
    mCsrUserConfig = (UINT32)Data;
    if (OcIsSipEnabled (EFI_SUCCESS, mCsrUserConfig)) {
      DEBUG ((DEBUG_WARN, "BEP: Specified value 0x%X will not disable SIP!\n", mCsrUserConfig));
    }
  } else {
    mCsrUserConfig = OC_CSR_DISABLE_FLAGS; ///< Defaults.
  }

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &ImageHandle,
                  &gOcBootEntryProtocolGuid,
                  &mToggleSipBootEntryProtocol,
                  NULL
                  );
  return Status;
}