OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
KernelSupport.c
Go to the documentation of this file.
1
16#include "BootCompatInternal.h"
17
18#include <Guid/OcVariable.h>
20
21#include <Library/BaseLib.h>
22#include <Library/BaseMemoryLib.h>
23#include <Library/DebugLib.h>
26#include <Library/OcMachoLib.h>
27#include <Library/OcMemoryLib.h>
28#include <Library/OcMiscLib.h>
29#include <Library/OcStringLib.h>
30#include <Library/PrintLib.h>
31#include <Library/UefiBootServicesTableLib.h>
32#include <Library/UefiLib.h>
33#include <Library/UefiRuntimeServicesTableLib.h>
34
45STATIC
46VOID
48 IN OUT RT_RELOC_PROTECT_DATA *RtReloc,
49 IN UINTN MemoryMapSize,
50 IN UINTN DescriptorSize,
51 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
52 IN EFI_PHYSICAL_ADDRESS SysTableArea,
53 IN UINTN SysTableAreaSize
54 )
55{
56 //
57 // We protect RT data & code from relocation by marking them MemMapIO except EFI_SYSTEM_TABLE area.
58 //
59 // This fixes NVRAM issues on some boards where access to NVRAM after boot services is possible
60 // only in SMM mode. RT driver passes data to SMM handler through previously negotiated buffer
61 // and this buffer must not be relocated.
62 // Explained and examined in detail by CodeRush and night199uk:
63 // https://web.archive.org/web/20141025080709/http://www.projectosx.com/forum/lofiversion/index.php/t3298.html
64 //
65 // Starting with APTIO V for NVRAM to work not only RT data but RT code too can no longer be moved
66 // due to the use of commbuffers. This, however, creates a memory protection issue, because
67 // XNU maps RT data as RW and code as RX, and AMI appears use global variables in some RT drivers.
68 // For this reason we shim (most?) affected RT services via wrapers that unset the WP bit during
69 // the UEFI call and set it back on return in a separate driver.
70 // Explained in detail by Download-Fritz and vit9696:
71 // http://www.insanelymac.com/forum/topic/331381-aptiomemoryfix (first 2 links in particular).
72 //
73 // EFI_SYSTEM_TABLE is passed directly through kernel boot arguments, and thus goes through static
74 // mapping (ml_static_ptovirt) in efi_set_tables_64 call. This mapping works as PHYS | CONST = VIRT.
75 // To avoid kernel accessing unmapped virtual address we let boot.efi relocate the page with
76 // EFI_SYSTEM_TABLE area. While technically it is possible to let the original page to be relocated,
77 // we pick a safer root by using a private copy.
78 //
79 // The primary downside of this approach is that boot.efi will still reserve the contiguous memory
80 // for runtime services after the kernel: efiRuntimeServicesPageCount pages starting from
81 // efiRuntimeServicesPageStart within kaddr ~ ksize range. However, unlike Macs, which have reserved
82 // gaps only for ACPI NVS, MemMapIO and similar regions, with this approach almost no physical memory
83 // in efiRuntimeServicesPageStart area is used at all. This memory is never reclaimed by XNU, which
84 // marks it as allocated in i386_vm_init. Expirements show that at least 85 MBs (Z170) are used for
85 // this process. On server systems the issue is much worse due to many devices in place.
86 // Ideally boot.efi should only count RT code and RT data pages, but it is not easy to change.
87 //
88
89 UINTN NumEntries;
90 UINTN Index;
91 EFI_MEMORY_DESCRIPTOR *Desc;
92 RT_RELOC_PROTECT_INFO *RelocInfo;
93
94 Desc = MemoryMap;
95 RtReloc->NumEntries = 0;
96 RelocInfo = &RtReloc->RelocInfo[0];
97 NumEntries = MemoryMapSize / DescriptorSize;
98
99 for (Index = 0; Index < NumEntries; ++Index) {
100 if ( ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0)
101 && (Desc->NumberOfPages > 0)
102 && ((Desc->Type == EfiRuntimeServicesCode) || (Desc->Type == EfiRuntimeServicesData))
103 && !AREA_WITHIN_DESCRIPTOR (Desc, SysTableArea, SysTableAreaSize))
104 {
105 if (RtReloc->NumEntries == ARRAY_SIZE (RtReloc->RelocInfo)) {
107 (
108 DEBUG_ERROR,
109 "OCABC: Cannot save mem type for entry: %Lx (type 0x%x)\n",
110 (UINT64)Desc->PhysicalStart,
111 (UINT32)Desc->Type
112 )
113 );
114 return;
115 }
116
117 RelocInfo->PhysicalStart = Desc->PhysicalStart;
118 RelocInfo->PhysicalEnd = LAST_DESCRIPTOR_ADDR (Desc);
119 RelocInfo->Type = Desc->Type;
120 Desc->Type = EfiMemoryMappedIO;
121 ++RelocInfo;
122 ++RtReloc->NumEntries;
123 }
124
125 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
126 }
127}
128
141STATIC
142EFI_STATUS
144 IN OUT KERNEL_SUPPORT_STATE *KernelState,
145 IN UINTN MemoryMapSize,
146 IN UINTN DescriptorSize,
147 IN UINT32 DescriptorVersion,
148 IN EFI_MEMORY_DESCRIPTOR *MemoryMap
149 )
150{
151 //
152 // About partial memmap:
153 // Some UEFIs are converting pointers to virtual addresses even if they do not
154 // point to regions with RT flag. This means that those UEFIs are using
155 // Desc->VirtualStart even for non-RT regions. Linux had issues with this:
156 // http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7cb00b72876ea2451eb79d468da0e8fb9134aa8a
157 // They are doing it Windows way now - copying RT descriptors to separate
158 // mem map and passing that stripped map to SetVirtualAddressMap().
159 // We'll do the same, although it seems that just assigning
160 // VirtualStart = PhysicalStart for non-RT areas also does the job.
161 //
162 // About virtual to physical mappings:
163 // Also adds virtual to physical address mappings for RT areas. This is needed since
164 // SetVirtualAddressMap() does not work on my Aptio without that. Probably because some driver
165 // has a bug and is trying to access new virtual addresses during the change.
166 // Linux and Windows are doing the same thing and problem is
167 // not visible there.
168 //
169
170 UINTN NumEntries;
171 UINTN Index;
172 EFI_MEMORY_DESCRIPTOR *Desc;
173 EFI_MEMORY_DESCRIPTOR *VirtualDesc;
174 EFI_STATUS Status;
176
177 Desc = MemoryMap;
178 NumEntries = MemoryMapSize / DescriptorSize;
179 VirtualDesc = KernelState->VmMap;
180 KernelState->VmMapSize = 0;
181 KernelState->VmMapDescSize = DescriptorSize;
182
183 //
184 // Get current VM page table.
185 //
186 PageTable = OcGetCurrentPageTable (NULL);
187
188 for (Index = 0; Index < NumEntries; ++Index) {
189 //
190 // Legacy note. Some UEFIs end up with "reserved" area with EFI_MEMORY_RUNTIME flag set when
191 // Intel HD3000 or HD4000 is used. For example, on GA-H81N-D2H there is a single 1 GB descriptor:
192 // 000000009F800000-00000000DF9FFFFF 0000000000040200 8000000000000000
193 //
194 // All known boot.efi starting from at least 10.5.8 properly handle this flag and do not assign
195 // virtual addresses to reserved descriptors. However, our legacy code had a bug, and did not
196 // check for EfiReservedMemoryType. Therefore it replaced such entries by EfiMemoryMappedIO
197 // to "prevent" boot.efi relocations.
198 //
199 // The relevant discussion and the original fix can be found here:
200 // http://web.archive.org/web/20141111124211/http://www.projectosx.com:80/forum/lofiversion/index.php/t2428-450.html
201 // https://sourceforge.net/p/cloverefiboot/code/605/
202 //
203 // The correct approach is to properly handle EfiReservedMemoryType with EFI_MEMORY_RUNTIME
204 // attribute set, and not mess with the memory map passed to boot.efi. As done here.
205 //
206 if ((Desc->Type != EfiReservedMemoryType) && ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0)) {
207 //
208 // Check if there is enough space in virtual map.
209 //
210 if (KernelState->VmMapSize + DescriptorSize > sizeof (KernelState->VmMap)) {
211 RUNTIME_DEBUG ((DEBUG_ERROR, "OCABC: Too many RT entries to memory map\n"));
212 return EFI_OUT_OF_RESOURCES;
213 }
214
215 //
216 // Copy region with EFI_MEMORY_RUNTIME flag to virtual map.
217 //
218 CopyMem (VirtualDesc, Desc, DescriptorSize);
219
220 //
221 // Define virtual to physical mapping.
222 //
223 Status = VmMapVirtualPages (
224 &KernelState->VmContext,
225 PageTable,
226 Desc->VirtualStart,
227 Desc->NumberOfPages,
228 Desc->PhysicalStart
229 );
230 if (EFI_ERROR (Status)) {
231 RUNTIME_DEBUG ((DEBUG_ERROR, "OCABC: RT mapping failure - %r\n", Status));
232 return EFI_OUT_OF_RESOURCES;
233 }
234
235 //
236 // Proceed to next virtual map slot.
237 //
238 VirtualDesc = NEXT_MEMORY_DESCRIPTOR (VirtualDesc, DescriptorSize);
239 KernelState->VmMapSize += DescriptorSize;
240 }
241
242 //
243 // Proceed to next original map slot.
244 //
245 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
246 }
247
248 VmFlushCaches ();
249
250 Status = gRT->SetVirtualAddressMap (
251 KernelState->VmMapSize,
252 DescriptorSize,
253 DescriptorVersion,
254 KernelState->VmMap
255 );
256
257 return Status;
258}
259
268STATIC
269VOID
271 IN RT_RELOC_PROTECT_DATA *RtReloc,
272 IN UINTN MemoryMapSize,
273 IN UINTN DescriptorSize,
274 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap
275 )
276{
277 UINTN Index;
278 UINTN Index2;
279 UINTN NumEntriesLeft;
280 UINTN NumEntries;
281 EFI_PHYSICAL_ADDRESS PhysicalStart;
282 EFI_PHYSICAL_ADDRESS PhysicalEnd;
283 EFI_MEMORY_DESCRIPTOR *Desc;
284
285 NumEntriesLeft = RtReloc->NumEntries;
286 NumEntries = MemoryMapSize / DescriptorSize;
287 Desc = MemoryMap;
288
289 for (Index = 0; Index < NumEntries && NumEntriesLeft > 0; ++Index) {
290 PhysicalStart = Desc->PhysicalStart;
291 PhysicalEnd = LAST_DESCRIPTOR_ADDR (Desc);
292
293 for (Index2 = 0; Index2 < RtReloc->NumEntries; ++Index2) {
294 //
295 // PhysicalStart match is enough, but just in case.
296 // Some types of firmware, such as on the Lenovo ThinkPad X240, have unusual reserved areas.
297 // For example, 0000000000000000-FFFFFFFFFFFFFFFF 0000000000000000 0000000000000000.
298 // Execute exact comparisons as fuzzy matching often results in errors.
299 //
300 if ( (PhysicalStart == RtReloc->RelocInfo[Index2].PhysicalStart)
301 && (PhysicalEnd == RtReloc->RelocInfo[Index2].PhysicalEnd))
302 {
303 Desc->Type = RtReloc->RelocInfo[Index2].Type;
304 --NumEntriesLeft;
305 break;
306 }
307 }
308
309 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
310 }
311
312 if (NumEntriesLeft > 0) {
314 (
315 DEBUG_ERROR,
316 "OCABC: Failed to restore %u entries out of %u\n",
317 (UINT32)NumEntriesLeft,
318 (UINT32)RtReloc->NumEntries
319 )
320 );
321 }
322}
323
324VOID
326 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
327 IN OUT VOID *BootArgs
328 )
329{
330 EFI_STATUS Status;
331 DTEntry Chosen;
332 CHAR8 *ArgsStr;
333 UINT32 ArgsSize;
335 UINTN MemoryMapSize;
336 EFI_MEMORY_DESCRIPTOR *MemoryMap;
337 UINTN DescriptorSize;
338
339 OcParseBootArgs (&BA, BootArgs);
340
341 if (BootCompat->Settings.ProvideCustomSlide) {
342 //
343 // Restore the variables we tampered with to support custom slides.
344 //
345 AppleSlideRestore (BootCompat, &BA);
346 }
347
348 if (BootCompat->Settings.DisableSingleUser) {
349 //
350 // First, there is a BootArgs entry for XNU.
351 //
353 }
354
355 if ( BootCompat->Settings.DisableSingleUser
356 || BootCompat->Settings.ForceBooterSignature)
357 {
358 DTInit ((VOID *)(UINTN)*BA.DeviceTreeP, BA.DeviceTreeLength);
359 Status = DTLookupEntry (NULL, "/chosen", &Chosen);
360 if (!EFI_ERROR (Status)) {
361 if (BootCompat->Settings.DisableSingleUser) {
362 //
363 // Second, there is a DT entry.
364 //
365 Status = DTGetProperty (Chosen, "boot-args", (VOID **)&ArgsStr, &ArgsSize);
366 if (!EFI_ERROR (Status) && (ArgsSize > 0)) {
367 OcRemoveArgumentFromCmd (ArgsStr, "-s");
368 }
369 }
370
371 if (BootCompat->Settings.ForceBooterSignature) {
372 Status = DTGetProperty (Chosen, "boot-signature", (VOID **)&ArgsStr, &ArgsSize);
373 if (!EFI_ERROR (Status) && (ArgsSize == SHA1_DIGEST_SIZE)) {
374 CopyMem (ArgsStr, BootCompat->Settings.BooterSignature, ArgsSize);
375 }
376 }
377 }
378 }
379
380 if ((BootCompat->KernelState.RelocationBlock != 0) && !BootCompat->KernelState.RelocationBlockLegacy) {
381 //
382 // When using Relocation Block, EfiBoot on macOS 10.6 and newer will not virtualize the addresses
383 // since they cannot be mapped 1:1 due to any region from the relocation block being outside
384 // of static XNU vaddr to paddr mapping. This causes a clean early exit in their
385 // SetVirtualAddressMap calling routine avoiding gRT->SetVirtualAddressMap.
386 //
387 // For this reason we need to perform it ourselves right here before we restored
388 // runtime memory protections as we also need to defragment EFI_SYSTEM_TABLE memory
389 // to be accessible from XNU.
390 //
391 AppleRelocationVirtualize (BootCompat, &BA);
392 }
393
394 if (BootCompat->Settings.AvoidRuntimeDefrag) {
395 MemoryMapSize = *BA.MemoryMapSize;
396 MemoryMap = (EFI_MEMORY_DESCRIPTOR *)(UINTN)(*BA.MemoryMap);
397 DescriptorSize = *BA.MemoryMapDescriptorSize;
398
399 //
400 // We must restore EfiRuntimeServicesCode memory area types, because otherwise
401 // RuntimeServices won't be mapped.
402 //
404 &BootCompat->RtReloc,
405 MemoryMapSize,
406 DescriptorSize,
407 MemoryMap
408 );
409
410 //
411 // On native Macs due to EfiBoot defragmentation it is guaranteed that
412 // VADDR % BASE_1GB == PADDR. macOS 11 started to rely on this in
413 // acpi_count_enabled_logical_processors, which needs to access MADT (APIC)
414 // ACPI table, and does that through ConfigurationTables.
415 //
416 // The simplest approach is to just copy the table, so that it is accessible
417 // at both actual mapping and 1:1 defragmented mapping. This should be safe,
418 // as the memory for 1:1 defragmented mapping is reserved by EfiBoot in the
419 // first place and is otherwise stolen anyway.
420 //
421 if (BootCompat->KernelState.ConfigurationTable != NULL) {
422 CopyMem (
423 (VOID *)((UINTN)BA.SystemTable->ConfigurationTable & (BASE_1GB - 1)),
424 BootCompat->KernelState.ConfigurationTable,
425 sizeof (*BootCompat->KernelState.ConfigurationTable) * BA.SystemTable->NumberOfTableEntries
426 );
427 }
428 }
429
430 if (BootCompat->KernelState.RelocationBlock != 0) {
431 AppleRelocationRebase (BootCompat, &BA);
432 }
433}
434
435VOID
437 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
438 IN UINTN ImageHeaderPage
439 )
440{
441 IOHibernateImageHeader *ImageHeader;
442 IOHibernateHandoff *Handoff;
443
444 ImageHeader = (IOHibernateImageHeader *)EFI_PAGES_TO_SIZE (ImageHeaderPage);
445
446 //
447 // Legacy note. In legacy implementations systemTableOffset was unconditionally overwritten
448 // with a wrong address due to ImageHeader->runtimePages not being converted from pages to bytes.
449 // Fortunately systemTableOffset was unused when kIOHibernateHandoffTypeMemoryMap is unspecified.
450 // systemTableOffset is calculated properly by boot.efi itself starting from 10.6.8 at least,
451 // and thus this assignment was useless in the first place.
452 //
453
454 //
455 // At this step we have two routes.
456 //
457 // 1. Remove newly generated memory map from hibernate image to let XNU use the original mapping.
458 // This is known to work well on most systems primarily because Windows requires UEFI firmware
459 // to preserve physical memory consistency at S4 wake. "On a UEFI platform, firmware runtime memory
460 // must be consistent across S4 sleep state transitions, in both size and location.", see:
461 // https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-uefi#hibernation-state-s4-transition-requirements
462 // 2. Recover memory map just as we do for normal booting. This created issues on some types of firmware
463 // resulting in unusual memory maps after S4 wake. In other cases, this should not immediately
464 // break things. XNU will entirely remove efiRuntimeServicesPageStart/efiRuntimeServicesPageSize
465 // mapping and our new memory map entries will unconditionally overwrite previous ones. In case
466 // no physical memory changes happened, this should work fine.
467 //
468 Handoff = (IOHibernateHandoff *)EFI_PAGES_TO_SIZE ((UINTN)ImageHeader->handoffPages);
469 while (Handoff->type != kIOHibernateHandoffTypeEnd) {
470 if (Handoff->type == kIOHibernateHandoffTypeMemoryMap) {
471 if (BootCompat->Settings.DiscardHibernateMap) {
472 //
473 // Route 1. Discard the new memory map here, and let XNU use what it had.
474 // It is unknown whether there are still examples of firmware that need this.
475 //
476 Handoff->type = kIOHibernateHandoffType;
477 } else {
478 //
479 // Route 2. Recovery memory protection types just as normal boot.
480 //
481
482 if (BootCompat->KernelState.VmMapDescSize == 0) {
483 RUNTIME_DEBUG ((DEBUG_ERROR, "OCABC: Saved descriptor size cannot be 0\n"));
484 return;
485 }
486
487 //
488 // TODO: If we try to work on hibernation support with relocation block
489 // We will need to add a call similar to AppleRelocationVirtualize here.
490 //
491
492 if (BootCompat->Settings.AvoidRuntimeDefrag) {
493 //
494 // I think we should not be there, but ideally all quirks are relatively independent.
495 //
497 &BootCompat->RtReloc,
498 Handoff->bytecount,
499 BootCompat->KernelState.VmMapDescSize,
500 (EFI_MEMORY_DESCRIPTOR *)(UINTN)Handoff->data
501 );
502 }
503 }
504
505 break;
506 }
507
508 Handoff = (IOHibernateHandoff *)((UINTN)Handoff + sizeof (Handoff) + Handoff->bytecount);
509 }
510
511 //
512 // TODO: To support hibernation with relocation block we will need to add a call similar
513 // to AppleRelocationRebase here.
514 //
515}
516
517VOID
519 IN OUT BOOT_COMPAT_CONTEXT *BootCompat
520 )
521{
522 EFI_STATUS Status;
523
524 if ( !BootCompat->Settings.SetupVirtualMap
525 || (BootCompat->KernelState.VmContext.MemoryPool != NULL))
526 {
527 return;
528 }
529
530 Status = VmAllocateMemoryPool (
531 &BootCompat->KernelState.VmContext,
533 BootCompat->ServicePtrs.GetMemoryMap
534 );
535
536 if (EFI_ERROR (Status)) {
537 DEBUG ((DEBUG_ERROR, "OCABC: Memory pool allocation failure - %r\n", Status));
538 }
539}
540
541VOID
543 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
544 IN OUT EFI_LOADED_IMAGE *LoadedImage,
545 IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL
546 )
547{
548 EFI_STATUS Status;
549
550 //
551 // Allocate memory pool if needed.
552 //
554 BootCompat
555 );
556
557 if (BootCompat->Settings.AvoidRuntimeDefrag) {
558 if (BootCompat->KernelState.SysTableRtArea == 0) {
559 //
560 // Allocate RT data pages for copy of UEFI system table for kernel.
561 // This one also has to be 32-bit due to XNU BootArgs structure.
562 // The reason for this allocation to be required is because XNU uses static
563 // mapping for directly passed pointers (see ProtectRtMemoryFromRelocation).
564 //
565 BootCompat->KernelState.SysTableRtArea = BASE_4GB;
566 BootCompat->KernelState.SysTableRtAreaSize = gST->Hdr.HeaderSize;
567 Status = OcAllocatePagesFromTop (
568 EfiRuntimeServicesData,
569 EFI_SIZE_TO_PAGES (gST->Hdr.HeaderSize),
570 &BootCompat->KernelState.SysTableRtArea,
571 GetMemoryMap,
572 NULL,
573 NULL
574 );
575 if (EFI_ERROR (Status)) {
576 DEBUG ((
577 DEBUG_ERROR,
578 "OCABC: Failed to allocate system table memory - %r\n",
579 Status
580 ));
581 BootCompat->KernelState.SysTableRtArea = 0;
582 return;
583 }
584
585 //
586 // Copy UEFI system table to the new location.
587 //
588 CopyMem (
589 (VOID *)(UINTN)BootCompat->KernelState.SysTableRtArea,
590 gST,
591 gST->Hdr.HeaderSize
592 );
593 //
594 // Remember physical configuration table location.
595 //
596 BootCompat->KernelState.ConfigurationTable = gST->ConfigurationTable;
597 }
598
599 //
600 // Assign loaded image with custom system table.
601 //
602 LoadedImage->SystemTable =
603 (EFI_SYSTEM_TABLE *)(UINTN)BootCompat->KernelState.SysTableRtArea;
604 }
605}
606
607EFI_STATUS
609 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
610 IN UINTN MemoryMapSize,
611 IN UINTN DescriptorSize,
612 IN UINT32 DescriptorVersion,
613 IN EFI_MEMORY_DESCRIPTOR *MemoryMap
614 )
615{
616 EFI_STATUS Status;
617 UINTN NumEntries;
618 UINTN Index;
619 EFI_MEMORY_DESCRIPTOR *Desc;
620
621 //
622 // Protect RT areas from relocation by marking then MemMapIO.
623 //
624 if (BootCompat->Settings.AvoidRuntimeDefrag) {
626 &BootCompat->RtReloc,
627 MemoryMapSize,
628 DescriptorSize,
629 MemoryMap,
630 BootCompat->KernelState.SysTableRtArea,
631 BootCompat->KernelState.SysTableRtAreaSize
632 );
633 }
634
635 //
636 // macOS 10.4 and 10.5 always call SetVirtualAddressMap, even when using a relocation block.
637 // Perform adjustment of virtual addresses here to their final positions.
638 //
639 if (BootCompat->KernelState.RelocationBlockLegacy) {
640 Desc = MemoryMap;
641 NumEntries = MemoryMapSize / DescriptorSize;
642
643 for (Index = 0; Index < NumEntries; ++Index) {
644 if ( (Desc->VirtualStart >= BootCompat->KernelState.RelocationBlock + BootCompat->KernelState.RelocationBlockUsed)
645 && (Desc->VirtualStart < BootCompat->KernelState.RelocationBlock + ESTIMATED_KERNEL_SIZE))
646 {
647 Desc->VirtualStart -= BootCompat->KernelState.RelocationBlock - KERNEL_BASE_PADDR;
648 }
649
650 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
651 }
652 }
653
654 //
655 // Virtualize RT services with all needed fixes.
656 //
657 if (BootCompat->Settings.SetupVirtualMap) {
659 &BootCompat->KernelState,
660 MemoryMapSize,
661 DescriptorSize,
662 DescriptorVersion,
663 MemoryMap
664 );
665 } else {
666 Status = gRT->SetVirtualAddressMap (
667 MemoryMapSize,
668 DescriptorSize,
669 DescriptorVersion,
670 MemoryMap
671 );
672 }
673
674 //
675 // Copy now virtualized UEFI system table for boot.efi to hand it to the kernel.
676 //
677 if (BootCompat->Settings.AvoidRuntimeDefrag) {
678 CopyMem (
679 (VOID *)(UINTN)BootCompat->KernelState.SysTableRtArea,
680 gST,
681 gST->Hdr.HeaderSize
682 );
683 }
684
685 return Status;
686}
@ kIOHibernateHandoffTypeEnd
@ kIOHibernateHandoffTypeMemoryMap
@ kIOHibernateHandoffType
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
VOID AppleSlideRestore(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN OUT OC_BOOT_ARGUMENTS *BootArgs)
EFI_STATUS AppleRelocationVirtualize(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN OUT OC_BOOT_ARGUMENTS *BA)
VOID AppleRelocationRebase(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN OUT OC_BOOT_ARGUMENTS *BA)
#define KERNEL_BASE_PADDR
#define ESTIMATED_KERNEL_SIZE
STATIC VOID ProtectRtMemoryFromRelocation(IN OUT RT_RELOC_PROTECT_DATA *RtReloc, IN UINTN MemoryMapSize, IN UINTN DescriptorSize, IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, IN EFI_PHYSICAL_ADDRESS SysTableArea, IN UINTN SysTableAreaSize)
STATIC EFI_STATUS PerformRtMemoryVirtualMapping(IN OUT KERNEL_SUPPORT_STATE *KernelState, IN UINTN MemoryMapSize, IN UINTN DescriptorSize, IN UINT32 DescriptorVersion, IN EFI_MEMORY_DESCRIPTOR *MemoryMap)
VOID AppleMapPrepareForHibernateWake(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN UINTN ImageHeaderPage)
VOID AppleMapPrepareBooterState(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN OUT EFI_LOADED_IMAGE *LoadedImage, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL)
EFI_STATUS AppleMapPrepareMemState(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN UINTN MemoryMapSize, IN UINTN DescriptorSize, IN UINT32 DescriptorVersion, IN EFI_MEMORY_DESCRIPTOR *MemoryMap)
VOID AppleMapPrepareMemoryPool(IN OUT BOOT_COMPAT_CONTEXT *BootCompat)
STATIC VOID RestoreProtectedRtMemoryTypes(IN RT_RELOC_PROTECT_DATA *RtReloc, IN UINTN MemoryMapSize, IN UINTN DescriptorSize, IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap)
VOID AppleMapPrepareForBooting(IN OUT BOOT_COMPAT_CONTEXT *BootCompat, IN OUT VOID *BootArgs)
VOID OcRemoveArgumentFromCmd(IN OUT CHAR8 *CommandLine, IN CONST CHAR8 *Argument)
VOID OcParseBootArgs(OUT OC_BOOT_ARGUMENTS *Arguments, IN VOID *BootArgs)
EFI_SYSTEM_TABLE * gST
#define SHA1_DIGEST_SIZE
Definition OcCryptoLib.h:44
#define RUNTIME_DEBUG(x)
EFI_STATUS DTLookupEntry(IN CONST DTEntry SearchPoint, IN CONST CHAR8 *PathName, IN DTEntry *FoundEntry)
VOID DTInit(IN VOID *Base, IN UINT32 *Length)
EFI_STATUS DTGetProperty(IN CONST DTEntry Entry, IN CHAR8 *PropertyName, IN VOID **PropertyValue, IN UINT32 *PropertySize)
#define AREA_WITHIN_DESCRIPTOR(Desc, Area, AreaSize)
Definition OcMemoryLib.h:39
PAGE_MAP_AND_DIRECTORY_POINTER * OcGetCurrentPageTable(OUT UINTN *Flags OPTIONAL)
VOID VmFlushCaches(VOID)
EFI_STATUS OcAllocatePagesFromTop(IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, IN OUT EFI_PHYSICAL_ADDRESS *Memory, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL, IN EFI_ALLOCATE_PAGES AllocatePages OPTIONAL, IN CHECK_ALLOCATION_RANGE CheckRange OPTIONAL)
Definition MemoryAlloc.c:27
EFI_STATUS VmMapVirtualPages(IN OUT OC_VMEM_CONTEXT *Context, IN OUT PAGE_MAP_AND_DIRECTORY_POINTER *PageTable OPTIONAL, IN EFI_VIRTUAL_ADDRESS VirtualAddr, IN UINT64 NumPages, IN EFI_PHYSICAL_ADDRESS PhysicalAddr)
#define LAST_DESCRIPTOR_ADDR(Desc)
Definition OcMemoryLib.h:32
EFI_STATUS VmAllocateMemoryPool(OUT OC_VMEM_CONTEXT *Context, IN UINTN NumPages, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL)
#define OC_DEFAULT_VMEM_PAGE_COUNT
Definition OcMemoryLib.h:45
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
EFI_SYSTEM_TABLE * SystemTable
EFI_PHYSICAL_ADDRESS PhysicalStart
EFI_PHYSICAL_ADDRESS PhysicalEnd