OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
ValidateMisc.c
Go to the documentation of this file.
1
16#include "ocvalidate.h"
17#include "OcValidateLib.h"
18#include "KextInfo.h"
19
20#include <Library/BaseLib.h>
23#include <Protocol/OcLog.h>
24
33STATIC
34BOOLEAN
36 IN CONST VOID *PrimaryEntry,
37 IN CONST VOID *SecondaryEntry
38 )
39{
40 //
41 // NOTE: Entries and Tools share the same constructor.
42 //
43 CONST OC_MISC_TOOLS_ENTRY *MiscEntriesPrimaryEntry;
44 CONST OC_MISC_TOOLS_ENTRY *MiscEntriesSecondaryEntry;
45 CONST CHAR8 *MiscEntriesPrimaryArgumentsString;
46 CONST CHAR8 *MiscEntriesSecondaryArgumentsString;
47 CONST CHAR8 *MiscEntriesPrimaryPathString;
48 CONST CHAR8 *MiscEntriesSecondaryPathString;
49
50 MiscEntriesPrimaryEntry = *(CONST OC_MISC_TOOLS_ENTRY **)PrimaryEntry;
51 MiscEntriesSecondaryEntry = *(CONST OC_MISC_TOOLS_ENTRY **)SecondaryEntry;
52 MiscEntriesPrimaryArgumentsString = OC_BLOB_GET (&MiscEntriesPrimaryEntry->Arguments);
53 MiscEntriesSecondaryArgumentsString = OC_BLOB_GET (&MiscEntriesSecondaryEntry->Arguments);
54 MiscEntriesPrimaryPathString = OC_BLOB_GET (&MiscEntriesPrimaryEntry->Path);
55 MiscEntriesSecondaryPathString = OC_BLOB_GET (&MiscEntriesSecondaryEntry->Path);
56
57 if (!MiscEntriesPrimaryEntry->Enabled || !MiscEntriesSecondaryEntry->Enabled) {
58 return FALSE;
59 }
60
61 if ( (AsciiStrCmp (MiscEntriesPrimaryArgumentsString, MiscEntriesSecondaryArgumentsString) == 0)
62 && (AsciiStrCmp (MiscEntriesPrimaryPathString, MiscEntriesSecondaryPathString) == 0))
63 {
64 DEBUG ((DEBUG_WARN, "Misc->Entries->Arguments: %a is duplicated ", MiscEntriesPrimaryPathString));
65 return TRUE;
66 }
67
68 return FALSE;
69}
70
79STATIC
80BOOLEAN
82 IN CONST VOID *PrimaryEntry,
83 IN CONST VOID *SecondaryEntry
84 )
85{
86 CONST OC_MISC_TOOLS_ENTRY *MiscToolsPrimaryEntry;
87 CONST OC_MISC_TOOLS_ENTRY *MiscToolsSecondaryEntry;
88 CONST CHAR8 *MiscToolsPrimaryArgumentsString;
89 CONST CHAR8 *MiscToolsSecondaryArgumentsString;
90 CONST CHAR8 *MiscToolsPrimaryPathString;
91 CONST CHAR8 *MiscToolsSecondaryPathString;
92 BOOLEAN MiscToolsPrimaryFullNvramAccess;
93 BOOLEAN MiscToolsSecondaryFullNvramAccess;
94
95 MiscToolsPrimaryEntry = *(CONST OC_MISC_TOOLS_ENTRY **)PrimaryEntry;
96 MiscToolsSecondaryEntry = *(CONST OC_MISC_TOOLS_ENTRY **)SecondaryEntry;
97 MiscToolsPrimaryArgumentsString = OC_BLOB_GET (&MiscToolsPrimaryEntry->Arguments);
98 MiscToolsSecondaryArgumentsString = OC_BLOB_GET (&MiscToolsSecondaryEntry->Arguments);
99 MiscToolsPrimaryPathString = OC_BLOB_GET (&MiscToolsPrimaryEntry->Path);
100 MiscToolsSecondaryPathString = OC_BLOB_GET (&MiscToolsSecondaryEntry->Path);
101 MiscToolsPrimaryFullNvramAccess = MiscToolsPrimaryEntry->FullNvramAccess;
102 MiscToolsSecondaryFullNvramAccess = MiscToolsSecondaryEntry->FullNvramAccess;
103
104 if (!MiscToolsPrimaryEntry->Enabled || !MiscToolsSecondaryEntry->Enabled) {
105 return FALSE;
106 }
107
108 if ( (AsciiStrCmp (MiscToolsPrimaryArgumentsString, MiscToolsSecondaryArgumentsString) == 0)
109 && (AsciiStrCmp (MiscToolsPrimaryPathString, MiscToolsSecondaryPathString) == 0)
110 && (MiscToolsPrimaryFullNvramAccess == MiscToolsSecondaryFullNvramAccess))
111 {
112 DEBUG ((DEBUG_WARN, "Misc->Tools->Path: %a is duplicated ", MiscToolsPrimaryPathString));
113 return TRUE;
114 }
115
116 return FALSE;
117}
118
126STATIC
127BOOLEAN
129 IN CONST CHAR8 *SecureBootModel
130 )
131{
132 UINTN Index;
133 STATIC CONST CHAR8 *AllowedSecureBootModel[] = {
134 "Default", "Disabled",
135 "j137", "j680", "j132", "j174", "j140k",
136 "j780", "j213", "j140a", "j152f", "j160",
137 "j230k", "j214k", "j223", "j215", "j185", "j185f",
138 "x86legacy"
139 };
140
141 for (Index = 0; Index < ARRAY_SIZE (AllowedSecureBootModel); ++Index) {
142 if (AsciiStrCmp (SecureBootModel, AllowedSecureBootModel[Index]) == 0) {
143 return TRUE;
144 }
145 }
146
147 return FALSE;
148}
149
150STATIC
151UINT32
153 IN OC_GLOBAL_CONFIG *Config
154 )
155{
156 UINT32 ErrorCount;
157 UINT32 Index;
158 UINTN Index2;
159 CONST CHAR8 *BlessOverrideEntry;
160 STATIC CONST CHAR8 *DisallowedBlessOverrideValues[] = {
161 "\\EFI\\Microsoft\\Boot\\bootmgfw.efi",
162 "\\System\\Library\\CoreServices\\boot.efi",
163 };
164
165 ErrorCount = 0;
166
167 for (Index = 0; Index < Config->Misc.BlessOverride.Count; ++Index) {
168 BlessOverrideEntry = OC_BLOB_GET (Config->Misc.BlessOverride.Values[Index]);
169
170 //
171 // &DisallowedBlessOverrideValues[][1] means no first '\\'.
172 //
173 for (Index2 = 0; Index2 < ARRAY_SIZE (DisallowedBlessOverrideValues); ++Index2) {
174 if ( (AsciiStrCmp (BlessOverrideEntry, DisallowedBlessOverrideValues[Index2]) == 0)
175 || (AsciiStrCmp (BlessOverrideEntry, &DisallowedBlessOverrideValues[Index2][1]) == 0))
176 {
177 DEBUG ((DEBUG_WARN, "Misc->BlessOverride: %a is redundant!\n", BlessOverrideEntry));
178 ++ErrorCount;
179 }
180 }
181 }
182
183 return ErrorCount;
184}
185
186STATIC
187UINT32
189 IN CONST CHAR8 *InstanceIdentifier
190 )
191{
192 UINT32 ErrorCount;
193 CHAR8 InstanceIdentifierCopy[OC_MAX_INSTANCE_IDENTIFIER_SIZE];
194 UINTN Length;
195
196 ErrorCount = 0;
197
198 if (AsciiStrSize (InstanceIdentifier) > OC_MAX_INSTANCE_IDENTIFIER_SIZE) {
199 DEBUG ((DEBUG_WARN, "Misc->Boot->InstanceIdentifier cannot be longer than %d bytes!\n", OC_MAX_INSTANCE_IDENTIFIER_SIZE));
200 ++ErrorCount;
201 } else {
202 if (AsciiStrStr (InstanceIdentifier, ",") != NULL) {
203 DEBUG ((DEBUG_WARN, "Misc->Boot->InstanceIdentifier cannot contain comma (,)!\n"));
204 ++ErrorCount;
205 }
206
207 //
208 // Illegal chars
209 //
210 Length = AsciiStrLen (InstanceIdentifier);
211 AsciiStrnCpyS (InstanceIdentifierCopy, OC_MAX_INSTANCE_IDENTIFIER_SIZE, InstanceIdentifier, Length);
212 AsciiFilterString (InstanceIdentifierCopy, TRUE);
213 if (OcAsciiStrniCmp (InstanceIdentifierCopy, InstanceIdentifier, Length) != 0) {
214 DEBUG ((DEBUG_WARN, "Misc->Boot->InstanceIdentifier cannot contain CR, LF, TAB or any other non-ASCII characters!\n"));
215 ++ErrorCount;
216 }
217 }
218
219 return ErrorCount;
220}
221
222STATIC
223UINT32
225 IN OC_GLOBAL_CONFIG *Config
226 )
227{
228 UINT32 ErrorCount;
229 UINT32 ConsoleAttributes;
230 CONST CHAR8 *HibernateMode;
231 UINT32 PickerAttributes;
232 UINT32 Index;
233 OC_UEFI_DRIVER_ENTRY *DriverEntry;
234 CONST CHAR8 *Driver;
235 BOOLEAN HasOpenCanopyEfiDriver;
236 CONST CHAR8 *PickerMode;
237 CONST CHAR8 *PickerVariant;
238 CONST CHAR8 *InstanceIdentifier;
239 UINTN PVSumSize;
240 UINTN PVPathFixedSize;
241 BOOLEAN IsPickerAudioAssistEnabled;
242 BOOLEAN IsAudioSupportEnabled;
243 CONST CHAR8 *LauncherOption;
244 CONST CHAR8 *LauncherPath;
245
246 ErrorCount = 0;
247
248 ConsoleAttributes = Config->Misc.Boot.ConsoleAttributes;
249 if ((ConsoleAttributes & ~0x7FU) != 0) {
250 DEBUG ((DEBUG_WARN, "Misc->Boot->ConsoleAttributes has unknown bits set!\n"));
251 ++ErrorCount;
252 }
253
254 HibernateMode = OC_BLOB_GET (&Config->Misc.Boot.HibernateMode);
255 if ( (AsciiStrCmp (HibernateMode, "None") != 0)
256 && (AsciiStrCmp (HibernateMode, "Auto") != 0)
257 && (AsciiStrCmp (HibernateMode, "RTC") != 0)
258 && (AsciiStrCmp (HibernateMode, "NVRAM") != 0))
259 {
260 DEBUG ((DEBUG_WARN, "Misc->Boot->HibernateMode is borked (Can only be None, Auto, RTC, or NVRAM)!\n"));
261 ++ErrorCount;
262 }
263
264 PickerAttributes = Config->Misc.Boot.PickerAttributes;
265 if ((PickerAttributes & ~OC_ATTR_ALL_BITS) != 0) {
266 DEBUG ((DEBUG_WARN, "Misc->Boot->PickerAttributes has unknown bits set!\n"));
267 ++ErrorCount;
268 }
269
270 HasOpenCanopyEfiDriver = FALSE;
271 for (Index = 0; Index < Config->Uefi.Drivers.Count; ++Index) {
272 DriverEntry = Config->Uefi.Drivers.Values[Index];
273 Driver = OC_BLOB_GET (&DriverEntry->Path);
274
275 if (DriverEntry->Enabled && (AsciiStrCmp (Driver, "OpenCanopy.efi") == 0)) {
276 HasOpenCanopyEfiDriver = TRUE;
277 }
278 }
279
280 PickerMode = OC_BLOB_GET (&Config->Misc.Boot.PickerMode);
281 if ( (AsciiStrCmp (PickerMode, "Builtin") != 0)
282 && (AsciiStrCmp (PickerMode, "External") != 0)
283 && (AsciiStrCmp (PickerMode, "Apple") != 0))
284 {
285 DEBUG ((DEBUG_WARN, "Misc->Boot->PickerMode is borked (Can only be Builtin, External, or Apple)!\n"));
286 ++ErrorCount;
287 } else if (HasOpenCanopyEfiDriver && (AsciiStrCmp (PickerMode, "External") != 0)) {
288 DEBUG ((DEBUG_WARN, "OpenCanopy.efi is loaded at UEFI->Drivers, but Misc->Boot->PickerMode is not set to External!\n"));
289 ++ErrorCount;
290 }
291
292 PickerVariant = OC_BLOB_GET (&Config->Misc.Boot.PickerVariant);
293 if (PickerVariant[0] == '\0') {
294 DEBUG ((DEBUG_WARN, "Misc->Boot->PickerVariant cannot be empty!\n"));
295 ++ErrorCount;
296 }
297
298 InstanceIdentifier = OC_BLOB_GET (&Config->Misc.Boot.InstanceIdentifier);
299 ErrorCount += ValidateInstanceIdentifier (InstanceIdentifier);
300
301 //
302 // Check the length of path relative to OC directory.
303 //
304 // There is one missing '\\' after the concatenation of PickerVariant and ExtAppleRecv10_15.icns (which has the longest length). Append one.
305 //
306 PVPathFixedSize = L_STR_LEN (OPEN_CORE_IMAGE_PATH) + 1 + L_STR_SIZE ("ExtAppleRecv10_15.icns");
307 PVSumSize = PVPathFixedSize + AsciiStrLen (PickerVariant);
308 if (PVSumSize > OC_STORAGE_SAFE_PATH_MAX) {
309 DEBUG ((
310 DEBUG_WARN,
311 "Misc->Boot->PickerVariant (length %u) is too long (should not exceed %u)!\n",
312 AsciiStrLen (PickerVariant),
313 OC_STORAGE_SAFE_PATH_MAX - PVPathFixedSize
314 ));
315 ++ErrorCount;
316 }
317
318 IsPickerAudioAssistEnabled = Config->Misc.Boot.PickerAudioAssist;
319 IsAudioSupportEnabled = Config->Uefi.Audio.AudioSupport;
320 if (IsPickerAudioAssistEnabled && !IsAudioSupportEnabled) {
321 DEBUG ((DEBUG_WARN, "Misc->Boot->PickerAudioAssist is enabled, but UEFI->Audio->AudioSupport is not enabled altogether!\n"));
322 ++ErrorCount;
323 }
324
325 LauncherOption = OC_BLOB_GET (&Config->Misc.Boot.LauncherOption);
326 if ( (AsciiStrCmp (LauncherOption, "Disabled") != 0)
327 && (AsciiStrCmp (LauncherOption, "Full") != 0)
328 && (AsciiStrCmp (LauncherOption, "Short") != 0)
329 && (AsciiStrCmp (LauncherOption, "System") != 0))
330 {
331 DEBUG ((DEBUG_WARN, "Misc->Boot->LauncherOption is borked (Can only be Disabled, Full, Short, or System)!\n"));
332 ++ErrorCount;
333 }
334
335 LauncherPath = OC_BLOB_GET (&Config->Misc.Boot.LauncherPath);
336 if (LauncherPath[0] == '\0') {
337 DEBUG ((DEBUG_WARN, "Misc->Boot->LauncherPath cannot be empty!\n"));
338 ++ErrorCount;
339 }
340
341 return ErrorCount;
342}
343
344STATIC
345UINT32
347 IN OC_GLOBAL_CONFIG *Config
348 )
349{
350 UINT32 ErrorCount;
351 UINT64 DisplayLevel;
352 UINT64 AllowedDisplayLevel;
353 UINT64 HaltLevel;
354 UINT64 AllowedHaltLevel;
355 UINT32 Target;
356
357 ErrorCount = 0;
358
359 //
360 // FIXME: Check whether DisplayLevel only supports values within AllowedDisplayLevel, or all possible levels in DebugLib.h?
361 //
362 DisplayLevel = Config->Misc.Debug.DisplayLevel;
363 AllowedDisplayLevel = DEBUG_WARN | DEBUG_INFO | DEBUG_VERBOSE | DEBUG_ERROR;
364 if ((DisplayLevel & ~AllowedDisplayLevel) != 0) {
365 DEBUG ((DEBUG_WARN, "Misc->Debug->DisplayLevel has unknown bits set!\n"));
366 ++ErrorCount;
367 }
368
369 HaltLevel = DisplayLevel;
370 AllowedHaltLevel = AllowedDisplayLevel;
371 if ((HaltLevel & ~AllowedHaltLevel) != 0) {
372 DEBUG ((DEBUG_WARN, "Misc->Security->HaltLevel has unknown bits set!\n"));
373 ++ErrorCount;
374 }
375
376 Target = Config->Misc.Debug.Target;
377 if ((Target & ~OC_LOG_ALL_BITS) != 0) {
378 DEBUG ((DEBUG_WARN, "Misc->Debug->Target has unknown bits set!\n"));
379 ++ErrorCount;
380 }
381
382 return ErrorCount;
383}
384
385STATIC
386UINT32
388 IN CHAR8 *EntryType,
389 IN UINT32 Index,
390 IN CONST CHAR8 *Flavour
391 )
392{
393 UINT32 ErrorCount;
394 CHAR8 FlavourCopy[OC_MAX_CONTENT_FLAVOUR_SIZE];
395 UINTN Length;
396 CONST CHAR8 *Start;
397 CONST CHAR8 *End;
398
399 ErrorCount = 0;
400
401 if ((Flavour == NULL) || (*Flavour == '\0')) {
402 DEBUG ((DEBUG_WARN, "Misc->%a[%u]->Flavour cannot be empty (use \"Auto\")!\n", EntryType, Index));
403 ++ErrorCount;
404 } else if (AsciiStrSize (Flavour) > OC_MAX_CONTENT_FLAVOUR_SIZE) {
405 DEBUG ((DEBUG_WARN, "Misc->%a[%u]->Flavour cannot be longer than %d bytes!\n", EntryType, Index, OC_MAX_CONTENT_FLAVOUR_SIZE));
406 ++ErrorCount;
407 } else {
408 //
409 // Illegal chars
410 //
411 Length = AsciiStrLen (Flavour);
412 AsciiStrnCpyS (FlavourCopy, OC_MAX_CONTENT_FLAVOUR_SIZE, Flavour, Length);
413 AsciiFilterString (FlavourCopy, TRUE);
414 if (OcAsciiStrniCmp (FlavourCopy, Flavour, Length) != 0) {
415 DEBUG ((DEBUG_WARN, "Flavour names within Misc->%a[%u]->Flavour cannot contain CR, LF, TAB or any other non-ASCII characters!\n", EntryType, Index));
416 ++ErrorCount;
417 }
418
419 //
420 // Per-name tests
421 //
422 End = Flavour - 1;
423 do {
424 for (Start = ++End; *End != '\0' && *End != ':'; ++End) {
425 }
426
427 if (Start == End) {
428 DEBUG ((DEBUG_WARN, "Flavour names within Misc->%a[%u]->Flavour cannot be empty!\n", EntryType, Index));
429 ++ErrorCount;
430 } else {
431 AsciiStrnCpyS (FlavourCopy, OC_MAX_CONTENT_FLAVOUR_SIZE, Start, End - Start);
432 if (OcAsciiStartsWith (FlavourCopy, "Ext", TRUE)) {
433 DEBUG ((DEBUG_WARN, "Flavour names within Misc->%a[%u]->Flavour cannot begin with \"Ext\"!\n", EntryType, Index));
434 ++ErrorCount;
435 }
436 }
437 } while (*End != '\0');
438 }
439
440 return ErrorCount;
441}
442
443STATIC
444UINT32
446 IN OC_GLOBAL_CONFIG *Config
447 )
448{
449 UINT32 ErrorCount;
450 UINT32 Index;
451 CONST CHAR8 *Arguments;
452 CONST CHAR8 *Comment;
453 CONST CHAR8 *AsciiName;
454 CONST CHAR16 *UnicodeName;
455 CONST CHAR8 *Path;
456 CONST CHAR8 *Flavour;
457
458 ErrorCount = 0;
459
460 for (Index = 0; Index < Config->Misc.Entries.Count; ++Index) {
461 Arguments = OC_BLOB_GET (&Config->Misc.Entries.Values[Index]->Arguments);
462 Comment = OC_BLOB_GET (&Config->Misc.Entries.Values[Index]->Comment);
463 AsciiName = OC_BLOB_GET (&Config->Misc.Entries.Values[Index]->Name);
464 Path = OC_BLOB_GET (&Config->Misc.Entries.Values[Index]->Path);
465 Flavour = OC_BLOB_GET (&Config->Misc.Entries.Values[Index]->Flavour);
466
467 //
468 // Sanitise strings.
469 //
470 // NOTE: As Arguments takes identical requirements of Comment,
471 // we use Comment sanitiser here.
472 //
473 if (!AsciiCommentIsLegal (Arguments)) {
474 DEBUG ((DEBUG_WARN, "Misc->Entries[%u]->Arguments contains illegal character!\n", Index));
475 ++ErrorCount;
476 }
477
478 if (!AsciiCommentIsLegal (Comment)) {
479 DEBUG ((DEBUG_WARN, "Misc->Entries[%u]->Comment contains illegal character!\n", Index));
480 ++ErrorCount;
481 }
482
483 UnicodeName = AsciiStrCopyToUnicode (AsciiName, 0);
484 if (UnicodeName != NULL) {
485 if (!UnicodeIsFilteredString (UnicodeName, TRUE)) {
486 DEBUG ((DEBUG_WARN, "Misc->Entries[%u]->Name contains illegal character!\n", Index));
487 ++ErrorCount;
488 }
489
490 FreePool ((VOID *)UnicodeName);
491 }
492
493 //
494 // FIXME: Properly sanitise Path.
495 //
496 if (!AsciiCommentIsLegal (Path)) {
497 DEBUG ((DEBUG_WARN, "Misc->Entries[%u]->Path contains illegal character!\n", Index));
498 ++ErrorCount;
499 }
500
501 ErrorCount += ValidateFlavour ("Entries", Index, Flavour);
502 }
503
504 //
505 // Check duplicated entries in Entries.
506 //
507 ErrorCount += FindArrayDuplication (
508 Config->Misc.Entries.Values,
509 Config->Misc.Entries.Count,
510 sizeof (Config->Misc.Entries.Values[0]),
512 );
513
514 return ErrorCount;
515}
516
517STATIC
518UINT32
520 IN OC_GLOBAL_CONFIG *Config
521 )
522{
523 UINT32 ErrorCount;
524 UINT32 Index;
525 BOOLEAN IsAuthRestartEnabled;
526 BOOLEAN HasVSMCKext;
527 CONST CHAR8 *AsciiDmgLoading;
528 UINT32 ExposeSensitiveData;
529 CONST CHAR8 *AsciiVault;
530 UINT32 ScanPolicy;
531 UINT32 AllowedScanPolicy;
532 CONST CHAR8 *SecureBootModel;
533
534 ErrorCount = 0;
535
536 HasVSMCKext = FALSE;
537 for (Index = 0; Index < Config->Kernel.Add.Count; ++Index) {
538 if (AsciiStrCmp (OC_BLOB_GET (&Config->Kernel.Add.Values[Index]->BundlePath), mKextInfo[INDEX_KEXT_VSMC].KextBundlePath) == 0) {
539 HasVSMCKext = TRUE;
540 }
541 }
542
543 IsAuthRestartEnabled = Config->Misc.Security.AuthRestart;
544 if (IsAuthRestartEnabled && !HasVSMCKext) {
545 DEBUG ((DEBUG_WARN, "Misc->Security->AuthRestart is enabled, but VirtualSMC is not loaded at Kernel->Add!\n"));
546 ++ErrorCount;
547 }
548
549 AsciiDmgLoading = OC_BLOB_GET (&Config->Misc.Security.DmgLoading);
550 if ( (AsciiStrCmp (AsciiDmgLoading, "Disabled") != 0)
551 && (AsciiStrCmp (AsciiDmgLoading, "Signed") != 0)
552 && (AsciiStrCmp (AsciiDmgLoading, "Any") != 0))
553 {
554 DEBUG ((DEBUG_WARN, "Misc->Security->DmgLoading is borked (Can only be Disabled, Signed, or Any)!\n"));
555 ++ErrorCount;
556 }
557
558 ExposeSensitiveData = Config->Misc.Security.ExposeSensitiveData;
559 if ((ExposeSensitiveData & ~OCS_EXPOSE_ALL_BITS) != 0) {
560 DEBUG ((DEBUG_WARN, "Misc->Security->ExposeSensitiveData has unknown bits set!\n"));
561 ++ErrorCount;
562 }
563
564 AsciiVault = OC_BLOB_GET (&Config->Misc.Security.Vault);
565 if ( (AsciiStrCmp (AsciiVault, "Optional") != 0)
566 && (AsciiStrCmp (AsciiVault, "Basic") != 0)
567 && (AsciiStrCmp (AsciiVault, "Secure") != 0))
568 {
569 DEBUG ((DEBUG_WARN, "Misc->Security->Vault is borked (Can only be Optional, Basic, or Secure)!\n"));
570 ++ErrorCount;
571 }
572
573 ScanPolicy = Config->Misc.Security.ScanPolicy;
575 //
576 // ScanPolicy can be zero (failsafe value), skipping such.
577 //
578 if (ScanPolicy != 0) {
579 if ((ScanPolicy & ~AllowedScanPolicy) != 0) {
580 DEBUG ((DEBUG_WARN, "Misc->Security->ScanPolicy has unknown bits set!\n"));
581 ++ErrorCount;
582 }
583
584 if (((ScanPolicy & OC_SCAN_FILE_SYSTEM_BITS) != 0) && ((ScanPolicy & OC_SCAN_FILE_SYSTEM_LOCK) == 0)) {
585 DEBUG ((DEBUG_WARN, "Misc->Security->ScanPolicy requests scanning filesystem, but OC_SCAN_FILE_SYSTEM_LOCK (bit 0) is not set!\n"));
586 ++ErrorCount;
587 }
588
589 if (((ScanPolicy & OC_SCAN_DEVICE_BITS) != 0) && ((ScanPolicy & OC_SCAN_DEVICE_LOCK) == 0)) {
590 DEBUG ((DEBUG_WARN, "Misc->Security->ScanPolicy requests scanning devices, but OC_SCAN_DEVICE_LOCK (bit 1) is not set!\n"));
591 ++ErrorCount;
592 }
593 }
594
595 //
596 // Validate SecureBootModel.
597 //
598 SecureBootModel = OC_BLOB_GET (&Config->Misc.Security.SecureBootModel);
599 if (!ValidateSecureBootModel (SecureBootModel)) {
600 DEBUG ((DEBUG_WARN, "Misc->Security->SecureBootModel is borked!\n"));
601 ++ErrorCount;
602 }
603
604 if ( !( (AsciiStrCmp (AsciiDmgLoading, "Disabled") == 0)
605 || (AsciiStrCmp (AsciiDmgLoading, "Signed") == 0)
606 || (AsciiDmgLoading[0] == '\0'))
607 && (AsciiStrCmp (SecureBootModel, "Disabled") != 0))
608 {
609 DEBUG ((DEBUG_WARN, "Misc->Security->DmgLoading must be Disabled or Signed unless Misc->Security->SecureBootModel is Disabled!\n"));
610 ++ErrorCount;
611 }
612
613 return ErrorCount;
614}
615
616STATIC
617BOOLEAN
619 IN UINT32 BaudRate
620 )
621{
622 UINTN Index;
623
624 //
625 // Reference:
626 // https://github.com/acidanthera/audk/blob/bb1bba3d776733c41dbfa2d1dc0fe234819a79f2/MdeModulePkg/MdeModulePkg.dec#L1223
627 //
628 STATIC CONST UINT32 AllowedBaudRate[] = {
629 921600U, 460800U, 230400U, 115200U,
630 57600U, 38400U, 19200U, 9600U, 7200U,
631 4800U, 3600U, 2400U, 2000U, 1800U,
632 1200U, 600U, 300U, 150U, 134U,
633 110U, 75U, 50U
634 };
635
636 for (Index = 0; Index < ARRAY_SIZE (AllowedBaudRate); ++Index) {
637 if (BaudRate == AllowedBaudRate[Index]) {
638 return TRUE;
639 }
640 }
641
642 DEBUG ((DEBUG_WARN, "Misc->Serial->BaudRate is borked!\n"));
643 DEBUG ((DEBUG_WARN, "Accepted BaudRate values:\n"));
644 for (Index = 0; Index < ARRAY_SIZE (AllowedBaudRate); ++Index) {
645 DEBUG ((DEBUG_WARN, "%u, ", AllowedBaudRate[Index]));
646 if ((Index != 0) && (Index % 5 == 0)) {
647 DEBUG ((DEBUG_WARN, "\n"));
648 }
649 }
650
651 DEBUG ((DEBUG_WARN, "\n"));
652 return FALSE;
653}
654
655STATIC
656UINT32
658 IN OC_GLOBAL_CONFIG *Config
659 )
660{
661 UINT32 ErrorCount;
662 UINT32 RegisterAccessWidth;
663 UINT32 BaudRate;
664 CONST UINT8 *PciDeviceInfo;
665 UINT32 PciDeviceInfoSize;
666
667 ErrorCount = 0;
668
669 //
670 // Reference:
671 // https://github.com/acidanthera/audk/blob/bb1bba3d776733c41dbfa2d1dc0fe234819a79f2/MdeModulePkg/MdeModulePkg.dec#L1199-L1200
672 //
673 RegisterAccessWidth = Config->Misc.Serial.Custom.RegisterAccessWidth;
674 if ((RegisterAccessWidth != 8U) && (RegisterAccessWidth != 32U)) {
675 DEBUG ((DEBUG_WARN, "Misc->Serial->RegisterAccessWidth can only be 8 or 32!\n"));
676 ++ErrorCount;
677 }
678
679 BaudRate = Config->Misc.Serial.Custom.BaudRate;
680 if (!ValidateBaudRate (BaudRate)) {
681 ++ErrorCount;
682 }
683
684 //
685 // Reference:
686 // https://github.com/acidanthera/audk/blob/bb1bba3d776733c41dbfa2d1dc0fe234819a79f2/MdeModulePkg/MdeModulePkg.dec#L1393
687 //
688 PciDeviceInfo = OC_BLOB_GET (&Config->Misc.Serial.Custom.PciDeviceInfo);
689 PciDeviceInfoSize = Config->Misc.Serial.Custom.PciDeviceInfo.Size;
690 if (PciDeviceInfoSize > OC_SERIAL_PCI_DEVICE_INFO_MAX_SIZE) {
691 DEBUG ((DEBUG_WARN, "Size of Misc->Serial->PciDeviceInfo cannot exceed %u!\n", OC_SERIAL_PCI_DEVICE_INFO_MAX_SIZE));
692 ++ErrorCount;
693 } else if (PciDeviceInfoSize == 0) {
694 DEBUG ((DEBUG_WARN, "Misc->Serial->PciDeviceInfo cannot be empty (use 0xFF instead)!\n"));
695 ++ErrorCount;
696 } else {
697 if (PciDeviceInfo[PciDeviceInfoSize - 1] != 0xFFU) {
698 DEBUG ((DEBUG_WARN, "Last byte of Misc->Serial->PciDeviceInfo must be 0xFF!\n"));
699 ++ErrorCount;
700 }
701
702 if ((PciDeviceInfoSize - 1) % 4 != 0) {
703 DEBUG ((DEBUG_WARN, "Misc->Serial->PciDeviceInfo must be divisible by 4 excluding the last 0xFF!\n"));
704 ++ErrorCount;
705 }
706 }
707
708 return ErrorCount;
709}
710
711STATIC
712UINT32
714 IN OC_GLOBAL_CONFIG *Config
715 )
716{
717 UINT32 ErrorCount;
718 UINT32 Index;
719 CONST CHAR8 *Arguments;
720 CONST CHAR8 *Comment;
721 CONST CHAR8 *AsciiName;
722 CONST CHAR16 *UnicodeName;
723 CONST CHAR8 *Path;
724 CONST CHAR8 *Flavour;
725
726 ErrorCount = 0;
727
728 for (Index = 0; Index < Config->Misc.Tools.Count; ++Index) {
729 Arguments = OC_BLOB_GET (&Config->Misc.Tools.Values[Index]->Arguments);
730 Comment = OC_BLOB_GET (&Config->Misc.Tools.Values[Index]->Comment);
731 AsciiName = OC_BLOB_GET (&Config->Misc.Tools.Values[Index]->Name);
732 Path = OC_BLOB_GET (&Config->Misc.Tools.Values[Index]->Path);
733 Flavour = OC_BLOB_GET (&Config->Misc.Tools.Values[Index]->Flavour);
734
735 //
736 // Sanitise strings.
737 //
738 // NOTE: As Arguments takes identical requirements of Comment,
739 // we use Comment sanitiser here.
740 //
741 if (!AsciiCommentIsLegal (Arguments)) {
742 DEBUG ((DEBUG_WARN, "Misc->Tools[%u]->Arguments contains illegal character!\n", Index));
743 ++ErrorCount;
744 }
745
746 if (!AsciiCommentIsLegal (Comment)) {
747 DEBUG ((DEBUG_WARN, "Misc->Tools[%u]->Comment contains illegal character!\n", Index));
748 ++ErrorCount;
749 }
750
751 //
752 // Check the length of path relative to OC directory.
753 //
754 if (L_STR_LEN (OPEN_CORE_TOOL_PATH) + AsciiStrSize (Path) > OC_STORAGE_SAFE_PATH_MAX) {
755 DEBUG ((DEBUG_WARN, "Misc->Tools[%u]->Path is too long (should not exceed %u)!\n", Index, OC_STORAGE_SAFE_PATH_MAX));
756 ++ErrorCount;
757 }
758
759 UnicodeName = AsciiStrCopyToUnicode (AsciiName, 0);
760 if (UnicodeName != NULL) {
761 if (!UnicodeIsFilteredString (UnicodeName, TRUE)) {
762 DEBUG ((DEBUG_WARN, "Misc->Tools[%u]->Name contains illegal character!\n", Index));
763 ++ErrorCount;
764 }
765
766 FreePool ((VOID *)UnicodeName);
767 }
768
769 //
770 // FIXME: Properly sanitise Path.
771 //
772 if (!AsciiCommentIsLegal (Path)) {
773 DEBUG ((DEBUG_WARN, "Misc->Tools[%u]->Path contains illegal character!\n", Index));
774 ++ErrorCount;
775 }
776
777 ErrorCount += ValidateFlavour ("Tools", Index, Flavour);
778 }
779
780 //
781 // Check duplicated entries in Tools.
782 //
783 ErrorCount += FindArrayDuplication (
784 Config->Misc.Tools.Values,
785 Config->Misc.Tools.Count,
786 sizeof (Config->Misc.Tools.Values[0]),
788 );
789
790 return ErrorCount;
791}
792
793UINT32
795 IN OC_GLOBAL_CONFIG *Config
796 )
797{
798 UINT32 ErrorCount;
799 UINTN Index;
800 STATIC CONFIG_CHECK MiscCheckers[] = {
808 };
809
810 DEBUG ((DEBUG_VERBOSE, "config loaded into %a!\n", __func__));
811
812 ErrorCount = 0;
813
814 for (Index = 0; Index < ARRAY_SIZE (MiscCheckers); ++Index) {
815 ErrorCount += MiscCheckers[Index](Config);
816 }
817
818 return ReportError (__func__, ErrorCount);
819}
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
UINT64 Start
EFI_DEVICE_PATH_PROTOCOL End
UINT64 Length
KEXT_INFO mKextInfo[]
Definition KextInfo.c:50
#define INDEX_KEXT_VSMC
Definition KextInfo.h:20
#define OC_ATTR_ALL_BITS
#define OC_SCAN_DEVICE_LOCK
#define OPEN_CORE_IMAGE_PATH
#define OC_SCAN_FILE_SYSTEM_LOCK
#define OC_SCAN_DEVICE_BITS
#define OC_MAX_INSTANCE_IDENTIFIER_SIZE
#define OC_SCAN_FILE_SYSTEM_BITS
#define OCS_EXPOSE_ALL_BITS
#define OC_SERIAL_PCI_DEVICE_INFO_MAX_SIZE
#define OC_MAX_CONTENT_FLAVOUR_SIZE
Definition OcFileLib.h:37
#define OC_LOG_ALL_BITS
Definition OcLog.h:37
#define OPEN_CORE_TOOL_PATH
Definition OcMainLib.h:62
#define OC_STORAGE_SAFE_PATH_MAX
VOID AsciiFilterString(IN OUT CHAR8 *String, IN BOOLEAN SingleLine)
Definition OcAsciiLib.c:480
#define L_STR_LEN(String)
Definition OcStringLib.h:26
BOOLEAN UnicodeIsFilteredString(IN CONST CHAR16 *String, IN BOOLEAN SingleLine)
#define L_STR_SIZE(String)
Definition OcStringLib.h:35
INTN EFIAPI OcAsciiStrniCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString, IN UINTN Length)
Definition OcAsciiLib.c:226
CHAR16 * AsciiStrCopyToUnicode(IN CONST CHAR8 *String, IN UINTN Length)
Definition OcAsciiLib.c:119
BOOLEAN EFIAPI OcAsciiStartsWith(IN CONST CHAR8 *String, IN CONST CHAR8 *SearchString, IN BOOLEAN CaseInsensitiveMatch)
Definition OcAsciiLib.c:291
#define OC_BLOB_GET(Blob)
UINT32 ReportError(IN CONST CHAR8 *FuncName, IN UINT32 ErrorCount)
UINT32 FindArrayDuplication(IN VOID *First, IN UINTN Number, IN UINTN Size, IN DUPLICATION_CHECK DupChecker)
BOOLEAN AsciiCommentIsLegal(IN CONST CHAR8 *Comment)
STATIC UINT32 CheckMiscBoot(IN OC_GLOBAL_CONFIG *Config)
UINT32 CheckMisc(IN OC_GLOBAL_CONFIG *Config)
STATIC UINT32 ValidateInstanceIdentifier(IN CONST CHAR8 *InstanceIdentifier)
STATIC UINT32 CheckMiscTools(IN OC_GLOBAL_CONFIG *Config)
STATIC BOOLEAN ValidateSecureBootModel(IN CONST CHAR8 *SecureBootModel)
STATIC BOOLEAN MiscToolsHasDuplication(IN CONST VOID *PrimaryEntry, IN CONST VOID *SecondaryEntry)
STATIC UINT32 CheckMiscEntries(IN OC_GLOBAL_CONFIG *Config)
STATIC BOOLEAN MiscEntriesHasDuplication(IN CONST VOID *PrimaryEntry, IN CONST VOID *SecondaryEntry)
STATIC UINT32 CheckMiscDebug(IN OC_GLOBAL_CONFIG *Config)
STATIC BOOLEAN ValidateBaudRate(IN UINT32 BaudRate)
STATIC UINT32 CheckMiscSecurity(IN OC_GLOBAL_CONFIG *Config)
STATIC UINT32 CheckBlessOverride(IN OC_GLOBAL_CONFIG *Config)
STATIC UINT32 ValidateFlavour(IN CHAR8 *EntryType, IN UINT32 Index, IN CONST CHAR8 *Flavour)
STATIC UINT32 CheckMiscSerial(IN OC_GLOBAL_CONFIG *Config)
UINT32(* CONFIG_CHECK)(IN OC_GLOBAL_CONFIG *Config)
Definition ocvalidate.h:27
CONST CHAR8 * KextBundlePath
Definition KextInfo.h:35