OpenCore  1.0.6
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 // Older EfiBoot (from 10.4.x) assigns virtual addresses to all descriptors containing
195 // EFI_MEMORY_RUNTIME flag, including ones with EfiReservedMemoryType. Starting with 10.5
196 // this is fixed, and virtual addresses are not assigned to reserved descriptors.
197 // We might eventually need to add some workaround to prevent exceeding virtual address space
198 // in EfiBoot from 10.4 by dropping the EFI_MEMORY_RUNTIME flag.
199 //
200 // The relevant discussion and the original fix can be found here:
201 // http://web.archive.org/web/20141111124211/http://www.projectosx.com:80/forum/lofiversion/index.php/t2428-450.html
202 // https://sourceforge.net/p/cloverefiboot/code/605/
203 //
204 // The correct approach is to properly handle EfiReservedMemoryType with EFI_MEMORY_RUNTIME
205 // attribute set, and not mess with the memory map passed to boot.efi. As done here.
206 //
207 if ((Desc->Type != EfiReservedMemoryType) && ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0)) {
208 //
209 // Check if there is enough space in virtual map.
210 //
211 if (KernelState->VmMapSize + DescriptorSize > sizeof (KernelState->VmMap)) {
212 RUNTIME_DEBUG ((DEBUG_ERROR, "OCABC: Too many RT entries to memory map\n"));
213 return EFI_OUT_OF_RESOURCES;
214 }
215
216 //
217 // Copy region with EFI_MEMORY_RUNTIME flag to virtual map.
218 //
219 CopyMem (VirtualDesc, Desc, DescriptorSize);
220
221 //
222 // Define virtual to physical mapping.
223 //
224 Status = VmMapVirtualPages (
225 &KernelState->VmContext,
226 PageTable,
227 Desc->VirtualStart,
228 Desc->NumberOfPages,
229 Desc->PhysicalStart
230 );
231 if (EFI_ERROR (Status)) {
232 RUNTIME_DEBUG ((DEBUG_ERROR, "OCABC: RT mapping failure - %r\n", Status));
233 return EFI_OUT_OF_RESOURCES;
234 }
235
236 //
237 // Proceed to next virtual map slot.
238 //
239 VirtualDesc = NEXT_MEMORY_DESCRIPTOR (VirtualDesc, DescriptorSize);
240 KernelState->VmMapSize += DescriptorSize;
241 }
242
243 //
244 // Proceed to next original map slot.
245 //
246 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
247 }
248
249 VmFlushCaches ();
250
251 Status = gRT->SetVirtualAddressMap (
252 KernelState->VmMapSize,
253 DescriptorSize,
254 DescriptorVersion,
255 KernelState->VmMap
256 );
257
258 return Status;
259}
260
269STATIC
270VOID
272 IN RT_RELOC_PROTECT_DATA *RtReloc,
273 IN UINTN MemoryMapSize,
274 IN UINTN DescriptorSize,
275 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap
276 )
277{
278 UINTN Index;
279 UINTN Index2;
280 UINTN NumEntriesLeft;
281 UINTN NumEntries;
282 EFI_PHYSICAL_ADDRESS PhysicalStart;
283 EFI_PHYSICAL_ADDRESS PhysicalEnd;
284 EFI_MEMORY_DESCRIPTOR *Desc;
285
286 NumEntriesLeft = RtReloc->NumEntries;
287 NumEntries = MemoryMapSize / DescriptorSize;
288 Desc = MemoryMap;
289
290 for (Index = 0; Index < NumEntries && NumEntriesLeft > 0; ++Index) {
291 PhysicalStart = Desc->PhysicalStart;
292 PhysicalEnd = LAST_DESCRIPTOR_ADDR (Desc);
293
294 for (Index2 = 0; Index2 < RtReloc->NumEntries; ++Index2) {
295 //
296 // PhysicalStart match is enough, but just in case.
297 // Some types of firmware, such as on the Lenovo ThinkPad X240, have unusual reserved areas.
298 // For example, 0000000000000000-FFFFFFFFFFFFFFFF 0000000000000000 0000000000000000.
299 // Execute exact comparisons as fuzzy matching often results in errors.
300 //
301 if ( (PhysicalStart == RtReloc->RelocInfo[Index2].PhysicalStart)
302 && (PhysicalEnd == RtReloc->RelocInfo[Index2].PhysicalEnd))
303 {
304 Desc->Type = RtReloc->RelocInfo[Index2].Type;
305 --NumEntriesLeft;
306 break;
307 }
308 }
309
310 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
311 }
312
313 if (NumEntriesLeft > 0) {
315 (
316 DEBUG_ERROR,
317 "OCABC: Failed to restore %u entries out of %u\n",
318 (UINT32)NumEntriesLeft,
319 (UINT32)RtReloc->NumEntries
320 )
321 );
322 }
323}
324
325VOID
327 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
328 IN OUT VOID *BootArgs
329 )
330{
331 EFI_STATUS Status;
332 DTEntry Chosen;
333 CHAR8 *ArgsStr;
334 UINT32 ArgsSize;
336 UINTN MemoryMapSize;
337 EFI_MEMORY_DESCRIPTOR *MemoryMap;
338 UINTN DescriptorSize;
339
340 OcParseBootArgs (&BA, BootArgs);
341
342 if (BootCompat->Settings.ProvideCustomSlide) {
343 //
344 // Restore the variables we tampered with to support custom slides.
345 //
346 AppleSlideRestore (BootCompat, &BA);
347 }
348
349 if (BootCompat->Settings.DisableSingleUser) {
350 //
351 // First, there is a BootArgs entry for XNU.
352 //
354 }
355
356 if ( BootCompat->Settings.DisableSingleUser
357 || BootCompat->Settings.ForceBooterSignature)
358 {
359 DTInit ((VOID *)(UINTN)*BA.DeviceTreeP, BA.DeviceTreeLength);
360 Status = DTLookupEntry (NULL, "/chosen", &Chosen);
361 if (!EFI_ERROR (Status)) {
362 if (BootCompat->Settings.DisableSingleUser) {
363 //
364 // Second, there is a DT entry.
365 //
366 Status = DTGetProperty (Chosen, "boot-args", (VOID **)&ArgsStr, &ArgsSize);
367 if (!EFI_ERROR (Status) && (ArgsSize > 0)) {
368 OcRemoveArgumentFromCmd (ArgsStr, "-s");
369 }
370 }
371
372 if (BootCompat->Settings.ForceBooterSignature) {
373 Status = DTGetProperty (Chosen, "boot-signature", (VOID **)&ArgsStr, &ArgsSize);
374 if (!EFI_ERROR (Status) && (ArgsSize == SHA1_DIGEST_SIZE)) {
375 CopyMem (ArgsStr, BootCompat->Settings.BooterSignature, ArgsSize);
376 }
377 }
378 }
379 }
380
381 if ((BootCompat->KernelState.RelocationBlock != 0) && !BootCompat->KernelState.RelocationBlockLegacy) {
382 //
383 // When using Relocation Block, EfiBoot on macOS 10.6 and newer will not virtualize the addresses
384 // since they cannot be mapped 1:1 due to any region from the relocation block being outside
385 // of static XNU vaddr to paddr mapping. This causes a clean early exit in their
386 // SetVirtualAddressMap calling routine avoiding gRT->SetVirtualAddressMap.
387 //
388 // For this reason we need to perform it ourselves right here before we restored
389 // runtime memory protections as we also need to defragment EFI_SYSTEM_TABLE memory
390 // to be accessible from XNU.
391 //
392 AppleRelocationVirtualize (BootCompat, &BA);
393 }
394
395 if (BootCompat->Settings.AvoidRuntimeDefrag) {
396 MemoryMapSize = *BA.MemoryMapSize;
397 MemoryMap = (EFI_MEMORY_DESCRIPTOR *)(UINTN)(*BA.MemoryMap);
398 DescriptorSize = *BA.MemoryMapDescriptorSize;
399
400 //
401 // We must restore EfiRuntimeServicesCode memory area types, because otherwise
402 // RuntimeServices won't be mapped.
403 //
405 &BootCompat->RtReloc,
406 MemoryMapSize,
407 DescriptorSize,
408 MemoryMap
409 );
410
411 //
412 // On native Macs due to EfiBoot defragmentation it is guaranteed that
413 // VADDR % BASE_1GB == PADDR. macOS 11 started to rely on this in
414 // acpi_count_enabled_logical_processors, which needs to access MADT (APIC)
415 // ACPI table, and does that through ConfigurationTables.
416 //
417 // The simplest approach is to just copy the table, so that it is accessible
418 // at both actual mapping and 1:1 defragmented mapping. This should be safe,
419 // as the memory for 1:1 defragmented mapping is reserved by EfiBoot in the
420 // first place and is otherwise stolen anyway.
421 //
422 if (BootCompat->KernelState.ConfigurationTable != NULL) {
423 CopyMem (
424 (VOID *)((UINTN)BA.SystemTable->ConfigurationTable & (BASE_1GB - 1)),
425 BootCompat->KernelState.ConfigurationTable,
426 sizeof (*BootCompat->KernelState.ConfigurationTable) * BA.SystemTable->NumberOfTableEntries
427 );
428 }
429 }
430
431 if (BootCompat->KernelState.RelocationBlock != 0) {
432 AppleRelocationRebase (BootCompat, &BA);
433 }
434}
435
436VOID
438 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
439 IN UINTN ImageHeaderPage
440 )
441{
442 IOHibernateImageHeader *ImageHeader;
443 IOHibernateHandoff *Handoff;
444
445 ImageHeader = (IOHibernateImageHeader *)EFI_PAGES_TO_SIZE (ImageHeaderPage);
446
447 //
448 // Legacy note. In legacy implementations systemTableOffset was unconditionally overwritten
449 // with a wrong address due to ImageHeader->runtimePages not being converted from pages to bytes.
450 // Fortunately systemTableOffset was unused when kIOHibernateHandoffTypeMemoryMap is unspecified.
451 // systemTableOffset is calculated properly by boot.efi itself starting from 10.6.8 at least,
452 // and thus this assignment was useless in the first place.
453 //
454
455 //
456 // At this step we have two routes.
457 //
458 // 1. Remove newly generated memory map from hibernate image to let XNU use the original mapping.
459 // This is known to work well on most systems primarily because Windows requires UEFI firmware
460 // to preserve physical memory consistency at S4 wake. "On a UEFI platform, firmware runtime memory
461 // must be consistent across S4 sleep state transitions, in both size and location.", see:
462 // https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-uefi#hibernation-state-s4-transition-requirements
463 // 2. Recover memory map just as we do for normal booting. This created issues on some types of firmware
464 // resulting in unusual memory maps after S4 wake. In other cases, this should not immediately
465 // break things. XNU will entirely remove efiRuntimeServicesPageStart/efiRuntimeServicesPageSize
466 // mapping and our new memory map entries will unconditionally overwrite previous ones. In case
467 // no physical memory changes happened, this should work fine.
468 //
469 Handoff = (IOHibernateHandoff *)EFI_PAGES_TO_SIZE ((UINTN)ImageHeader->handoffPages);
470 while (Handoff->type != kIOHibernateHandoffTypeEnd) {
471 if (Handoff->type == kIOHibernateHandoffTypeMemoryMap) {
472 if (BootCompat->Settings.DiscardHibernateMap) {
473 //
474 // Route 1. Discard the new memory map here, and let XNU use what it had.
475 // It is unknown whether there are still examples of firmware that need this.
476 //
477 Handoff->type = kIOHibernateHandoffType;
478 } else {
479 //
480 // Route 2. Recovery memory protection types just as normal boot.
481 //
482
483 if (BootCompat->KernelState.VmMapDescSize == 0) {
484 RUNTIME_DEBUG ((DEBUG_ERROR, "OCABC: Saved descriptor size cannot be 0\n"));
485 return;
486 }
487
488 //
489 // TODO: If we try to work on hibernation support with relocation block
490 // We will need to add a call similar to AppleRelocationVirtualize here.
491 //
492
493 if (BootCompat->Settings.AvoidRuntimeDefrag) {
494 //
495 // I think we should not be there, but ideally all quirks are relatively independent.
496 //
498 &BootCompat->RtReloc,
499 Handoff->bytecount,
500 BootCompat->KernelState.VmMapDescSize,
501 (EFI_MEMORY_DESCRIPTOR *)(UINTN)Handoff->data
502 );
503 }
504 }
505
506 break;
507 }
508
509 Handoff = (IOHibernateHandoff *)((UINTN)Handoff + sizeof (Handoff) + Handoff->bytecount);
510 }
511
512 //
513 // TODO: To support hibernation with relocation block we will need to add a call similar
514 // to AppleRelocationRebase here.
515 //
516}
517
518VOID
520 IN OUT BOOT_COMPAT_CONTEXT *BootCompat
521 )
522{
523 EFI_STATUS Status;
524
525 if ( !BootCompat->Settings.SetupVirtualMap
526 || (BootCompat->KernelState.VmContext.MemoryPool != NULL))
527 {
528 return;
529 }
530
531 Status = VmAllocateMemoryPool (
532 &BootCompat->KernelState.VmContext,
534 BootCompat->ServicePtrs.GetMemoryMap
535 );
536
537 if (EFI_ERROR (Status)) {
538 DEBUG ((DEBUG_ERROR, "OCABC: Memory pool allocation failure - %r\n", Status));
539 }
540}
541
542VOID
544 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
545 IN OUT EFI_LOADED_IMAGE *LoadedImage,
546 IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL
547 )
548{
549 EFI_STATUS Status;
550
551 //
552 // Allocate memory pool if needed.
553 //
555 BootCompat
556 );
557
558 if (BootCompat->Settings.AvoidRuntimeDefrag) {
559 if (BootCompat->KernelState.SysTableRtArea == 0) {
560 //
561 // Allocate RT data pages for copy of UEFI system table for kernel.
562 // This one also has to be 32-bit due to XNU BootArgs structure.
563 // The reason for this allocation to be required is because XNU uses static
564 // mapping for directly passed pointers (see ProtectRtMemoryFromRelocation).
565 //
566 BootCompat->KernelState.SysTableRtArea = BASE_4GB;
567 BootCompat->KernelState.SysTableRtAreaSize = gST->Hdr.HeaderSize;
568 Status = OcAllocatePagesFromTop (
569 EfiRuntimeServicesData,
570 EFI_SIZE_TO_PAGES (gST->Hdr.HeaderSize),
571 &BootCompat->KernelState.SysTableRtArea,
572 GetMemoryMap,
573 NULL,
574 NULL
575 );
576 if (EFI_ERROR (Status)) {
577 DEBUG ((
578 DEBUG_ERROR,
579 "OCABC: Failed to allocate system table memory - %r\n",
580 Status
581 ));
582 BootCompat->KernelState.SysTableRtArea = 0;
583 return;
584 }
585
586 DEBUG ((DEBUG_VERBOSE, "OCABC: Allocated SysTableRtArea %p\n", BootCompat->KernelState.SysTableRtArea));
587
588 //
589 // Copy UEFI system table to the new location.
590 //
591 CopyMem (
592 (VOID *)(UINTN)BootCompat->KernelState.SysTableRtArea,
593 gST,
594 gST->Hdr.HeaderSize
595 );
596 //
597 // Remember physical configuration table location.
598 //
599 BootCompat->KernelState.ConfigurationTable = gST->ConfigurationTable;
600 }
601
602 //
603 // Assign loaded image with custom system table.
604 //
605 LoadedImage->SystemTable =
606 (EFI_SYSTEM_TABLE *)(UINTN)BootCompat->KernelState.SysTableRtArea;
607 }
608}
609
610EFI_STATUS
612 IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
613 IN UINTN MemoryMapSize,
614 IN UINTN DescriptorSize,
615 IN UINT32 DescriptorVersion,
616 IN EFI_MEMORY_DESCRIPTOR *MemoryMap
617 )
618{
619 EFI_STATUS Status;
620 UINTN NumEntries;
621 UINTN Index;
622 EFI_MEMORY_DESCRIPTOR *Desc;
623
624 //
625 // Protect RT areas from relocation by marking then MemMapIO.
626 //
627 if (BootCompat->Settings.AvoidRuntimeDefrag) {
629 &BootCompat->RtReloc,
630 MemoryMapSize,
631 DescriptorSize,
632 MemoryMap,
633 BootCompat->KernelState.SysTableRtArea,
634 BootCompat->KernelState.SysTableRtAreaSize
635 );
636 }
637
638 //
639 // macOS 10.4 and 10.5 always call SetVirtualAddressMap, even when using a relocation block.
640 // Perform adjustment of virtual addresses here to their final positions.
641 //
642 if (BootCompat->KernelState.RelocationBlockLegacy) {
643 Desc = MemoryMap;
644 NumEntries = MemoryMapSize / DescriptorSize;
645
646 for (Index = 0; Index < NumEntries; ++Index) {
647 if ( (Desc->VirtualStart >= BootCompat->KernelState.RelocationBlock + BootCompat->KernelState.RelocationBlockUsed)
648 && (Desc->VirtualStart < BootCompat->KernelState.RelocationBlock + ESTIMATED_KERNEL_SIZE))
649 {
650 Desc->VirtualStart -= BootCompat->KernelState.RelocationBlock - KERNEL_BASE_PADDR;
651 }
652
653 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
654 }
655 }
656
657 //
658 // Virtualize RT services with all needed fixes.
659 //
660 if (BootCompat->Settings.SetupVirtualMap) {
662 &BootCompat->KernelState,
663 MemoryMapSize,
664 DescriptorSize,
665 DescriptorVersion,
666 MemoryMap
667 );
668 } else {
669 Status = gRT->SetVirtualAddressMap (
670 MemoryMapSize,
671 DescriptorSize,
672 DescriptorVersion,
673 MemoryMap
674 );
675 }
676
677 //
678 // Copy now virtualized UEFI system table for boot.efi to hand it to the kernel.
679 //
680 if (BootCompat->Settings.AvoidRuntimeDefrag) {
681 CopyMem (
682 (VOID *)(UINTN)BootCompat->KernelState.SysTableRtArea,
683 gST,
684 gST->Hdr.HeaderSize
685 );
686 }
687
688 return Status;
689}
@ 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