VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 20.8 KB
Line 
1/** @file
2
3 Generic non-coherent implementation of DmaLib.h
4
5 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
6 Copyright (c) 2015 - 2017, Linaro, Ltd. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include <PiDxe.h>
13#include <Library/BaseLib.h>
14#include <Library/DebugLib.h>
15#include <Library/DmaLib.h>
16#include <Library/DxeServicesTableLib.h>
17#include <Library/MemoryAllocationLib.h>
18#include <Library/UefiBootServicesTableLib.h>
19#include <Library/IoLib.h>
20#include <Library/BaseMemoryLib.h>
21
22#include <Protocol/Cpu.h>
23
24typedef struct {
25 EFI_PHYSICAL_ADDRESS HostAddress;
26 VOID *BufferAddress;
27 UINTN NumberOfBytes;
28 DMA_MAP_OPERATION Operation;
29 BOOLEAN DoubleBuffer;
30} MAP_INFO_INSTANCE;
31
32typedef struct {
33 LIST_ENTRY Link;
34 VOID *HostAddress;
35 UINTN NumPages;
36 UINT64 Attributes;
37} UNCACHED_ALLOCATION;
38
39STATIC EFI_CPU_ARCH_PROTOCOL *mCpu;
40STATIC LIST_ENTRY UncachedAllocationList;
41
42STATIC PHYSICAL_ADDRESS mDmaHostAddressLimit;
43
44STATIC
45PHYSICAL_ADDRESS
46HostToDeviceAddress (
47 IN VOID *Address
48 )
49{
50 return (PHYSICAL_ADDRESS)(UINTN)Address + PcdGet64 (PcdDmaDeviceOffset);
51}
52
53/**
54 Allocates one or more 4KB pages of a certain memory type at a specified
55 alignment.
56
57 Allocates the number of 4KB pages specified by Pages of a certain memory type
58 with an alignment specified by Alignment. The allocated buffer is returned.
59 If Pages is 0, then NULL is returned. If there is not enough memory at the
60 specified alignment remaining to satisfy the request, then NULL is returned.
61 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
62 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
63
64 @param MemoryType The type of memory to allocate.
65 @param Pages The number of 4 KB pages to allocate.
66 @param Alignment The requested alignment of the allocation.
67 Must be a power of two.
68 If Alignment is zero, then byte alignment is
69 used.
70
71 @return A pointer to the allocated buffer or NULL if allocation fails.
72
73**/
74STATIC
75VOID *
76InternalAllocateAlignedPages (
77 IN EFI_MEMORY_TYPE MemoryType,
78 IN UINTN Pages,
79 IN UINTN Alignment
80 )
81{
82 EFI_STATUS Status;
83 EFI_PHYSICAL_ADDRESS Memory;
84 UINTN AlignedMemory;
85 UINTN AlignmentMask;
86 UINTN UnalignedPages;
87 UINTN RealPages;
88
89 //
90 // Alignment must be a power of two or zero.
91 //
92 ASSERT ((Alignment & (Alignment - 1)) == 0);
93
94 if (Pages == 0) {
95 return NULL;
96 }
97
98 if (Alignment > EFI_PAGE_SIZE) {
99 //
100 // Calculate the total number of pages since alignment is larger than page
101 // size.
102 //
103 AlignmentMask = Alignment - 1;
104 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
105 //
106 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not
107 // overflow.
108 //
109 ASSERT (RealPages > Pages);
110
111 Memory = mDmaHostAddressLimit;
112 Status = gBS->AllocatePages (
113 AllocateMaxAddress,
114 MemoryType,
115 RealPages,
116 &Memory
117 );
118 if (EFI_ERROR (Status)) {
119 return NULL;
120 }
121
122 AlignedMemory = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask;
123 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory);
124 if (UnalignedPages > 0) {
125 //
126 // Free first unaligned page(s).
127 //
128 Status = gBS->FreePages (Memory, UnalignedPages);
129 ASSERT_EFI_ERROR (Status);
130 }
131
132 Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
133 UnalignedPages = RealPages - Pages - UnalignedPages;
134 if (UnalignedPages > 0) {
135 //
136 // Free last unaligned page(s).
137 //
138 Status = gBS->FreePages (Memory, UnalignedPages);
139 ASSERT_EFI_ERROR (Status);
140 }
141 } else {
142 //
143 // Do not over-allocate pages in this case.
144 //
145 Memory = mDmaHostAddressLimit;
146 Status = gBS->AllocatePages (
147 AllocateMaxAddress,
148 MemoryType,
149 Pages,
150 &Memory
151 );
152 if (EFI_ERROR (Status)) {
153 return NULL;
154 }
155
156 AlignedMemory = (UINTN)Memory;
157 }
158
159 return (VOID *)AlignedMemory;
160}
161
162/**
163 Provides the DMA controller-specific addresses needed to access system memory.
164
165 Operation is relative to the DMA bus master.
166
167 @param Operation Indicates if the bus master is going to read or
168 write to system memory.
169 @param HostAddress The system memory address to map to the DMA
170 controller.
171 @param NumberOfBytes On input the number of bytes to map. On output
172 the number of bytes that were mapped.
173 @param DeviceAddress The resulting map address for the bus master
174 controller to use to access the host's
175 HostAddress.
176 @param Mapping A resulting value to pass to Unmap().
177
178 @retval EFI_SUCCESS The range was mapped for the returned
179 NumberOfBytes.
180 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
181 buffer.
182 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
183 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
184 of resources.
185 @retval EFI_DEVICE_ERROR The system hardware could not map the requested
186 address.
187
188**/
189EFI_STATUS
190EFIAPI
191DmaMap (
192 IN DMA_MAP_OPERATION Operation,
193 IN VOID *HostAddress,
194 IN OUT UINTN *NumberOfBytes,
195 OUT PHYSICAL_ADDRESS *DeviceAddress,
196 OUT VOID **Mapping
197 )
198{
199 EFI_STATUS Status;
200 MAP_INFO_INSTANCE *Map;
201 VOID *Buffer;
202 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
203 UINTN AllocSize;
204
205 if ((HostAddress == NULL) ||
206 (NumberOfBytes == NULL) ||
207 (DeviceAddress == NULL) ||
208 (Mapping == NULL))
209 {
210 return EFI_INVALID_PARAMETER;
211 }
212
213 if (Operation >= MapOperationMaximum) {
214 return EFI_INVALID_PARAMETER;
215 }
216
217 *DeviceAddress = HostToDeviceAddress (HostAddress);
218
219 // Remember range so we can flush on the other side
220 Map = AllocatePool (sizeof (MAP_INFO_INSTANCE));
221 if (Map == NULL) {
222 return EFI_OUT_OF_RESOURCES;
223 }
224
225 if (((UINTN)HostAddress + *NumberOfBytes) > mDmaHostAddressLimit) {
226 if (Operation == MapOperationBusMasterCommonBuffer) {
227 goto CommonBufferError;
228 }
229
230 AllocSize = ALIGN_VALUE (*NumberOfBytes, mCpu->DmaBufferAlignment);
231 Map->BufferAddress = InternalAllocateAlignedPages (
232 EfiBootServicesData,
233 EFI_SIZE_TO_PAGES (AllocSize),
234 mCpu->DmaBufferAlignment
235 );
236 if (Map->BufferAddress == NULL) {
237 Status = EFI_OUT_OF_RESOURCES;
238 goto FreeMapInfo;
239 }
240
241 if (Operation == MapOperationBusMasterRead) {
242 CopyMem (Map->BufferAddress, (VOID *)(UINTN)HostAddress, *NumberOfBytes);
243 }
244
245 mCpu->FlushDataCache (
246 mCpu,
247 (UINTN)Map->BufferAddress,
248 AllocSize,
249 EfiCpuFlushTypeWriteBack
250 );
251
252 *DeviceAddress = HostToDeviceAddress (Map->BufferAddress);
253 } else if ((Operation != MapOperationBusMasterRead) &&
254 ((((UINTN)HostAddress & (mCpu->DmaBufferAlignment - 1)) != 0) ||
255 ((*NumberOfBytes & (mCpu->DmaBufferAlignment - 1)) != 0)))
256 {
257 // Get the cacheability of the region
258 Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
259 if (EFI_ERROR (Status)) {
260 goto FreeMapInfo;
261 }
262
263 // If the mapped buffer is not an uncached buffer
264 if ((GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) != 0) {
265 //
266 // Operations of type MapOperationBusMasterCommonBuffer are only allowed
267 // on uncached buffers.
268 //
269 if (Operation == MapOperationBusMasterCommonBuffer) {
270 goto CommonBufferError;
271 }
272
273 //
274 // If the buffer does not fill entire cache lines we must double buffer
275 // into a suitably aligned allocation that allows us to invalidate the
276 // cache without running the risk of corrupting adjacent unrelated data.
277 // Note that pool allocations are guaranteed to be 8 byte aligned, so
278 // we only have to add (alignment - 8) worth of padding.
279 //
280 Map->DoubleBuffer = TRUE;
281 AllocSize = ALIGN_VALUE (*NumberOfBytes, mCpu->DmaBufferAlignment) +
282 (mCpu->DmaBufferAlignment - 8);
283 Map->BufferAddress = AllocatePool (AllocSize);
284 if (Map->BufferAddress == NULL) {
285 Status = EFI_OUT_OF_RESOURCES;
286 goto FreeMapInfo;
287 }
288
289 Buffer = ALIGN_POINTER (Map->BufferAddress, mCpu->DmaBufferAlignment);
290 *DeviceAddress = HostToDeviceAddress (Buffer);
291
292 //
293 // Get rid of any dirty cachelines covering the double buffer. This
294 // prevents them from being written back unexpectedly, potentially
295 // overwriting the data we receive from the device.
296 //
297 mCpu->FlushDataCache (
298 mCpu,
299 (UINTN)Buffer,
300 *NumberOfBytes,
301 EfiCpuFlushTypeWriteBack
302 );
303 } else {
304 Map->DoubleBuffer = FALSE;
305 }
306 } else {
307 Map->DoubleBuffer = FALSE;
308
309 DEBUG_CODE_BEGIN ();
310
311 //
312 // The operation type check above only executes if the buffer happens to be
313 // misaligned with respect to CWG, but even if it is aligned, we should not
314 // allow arbitrary buffers to be used for creating consistent mappings.
315 // So duplicate the check here when running in DEBUG mode, just to assert
316 // that we are not trying to create a consistent mapping for cached memory.
317 //
318 Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
319 ASSERT_EFI_ERROR (Status);
320
321 ASSERT (
322 Operation != MapOperationBusMasterCommonBuffer ||
323 (GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) == 0
324 );
325
326 DEBUG_CODE_END ();
327
328 // Flush the Data Cache (should not have any effect if the memory region is
329 // uncached)
330 mCpu->FlushDataCache (
331 mCpu,
332 (UINTN)HostAddress,
333 *NumberOfBytes,
334 EfiCpuFlushTypeWriteBackInvalidate
335 );
336 }
337
338 Map->HostAddress = (UINTN)HostAddress;
339 Map->NumberOfBytes = *NumberOfBytes;
340 Map->Operation = Operation;
341
342 *Mapping = Map;
343
344 return EFI_SUCCESS;
345
346CommonBufferError:
347 DEBUG ((
348 DEBUG_ERROR,
349 "%a: Operation type 'MapOperationBusMasterCommonBuffer' is only "
350 "supported\non memory regions that were allocated using "
351 "DmaAllocateBuffer ()\n",
352 __func__
353 ));
354 Status = EFI_UNSUPPORTED;
355FreeMapInfo:
356 FreePool (Map);
357
358 return Status;
359}
360
361/**
362 Completes the DmaMapBusMasterRead(), DmaMapBusMasterWrite(), or
363 DmaMapBusMasterCommonBuffer() operation and releases any corresponding
364 resources.
365
366 @param Mapping The mapping value returned from DmaMap*().
367
368 @retval EFI_SUCCESS The range was unmapped.
369 @retval EFI_DEVICE_ERROR The data was not committed to the target system
370 memory.
371 @retval EFI_INVALID_PARAMETER An inconsistency was detected between the
372 mapping type and the DoubleBuffer field
373
374**/
375EFI_STATUS
376EFIAPI
377DmaUnmap (
378 IN VOID *Mapping
379 )
380{
381 MAP_INFO_INSTANCE *Map;
382 EFI_STATUS Status;
383 VOID *Buffer;
384 UINTN AllocSize;
385
386 if (Mapping == NULL) {
387 ASSERT (FALSE);
388 return EFI_INVALID_PARAMETER;
389 }
390
391 Map = (MAP_INFO_INSTANCE *)Mapping;
392
393 Status = EFI_SUCCESS;
394 if (((UINTN)Map->HostAddress + Map->NumberOfBytes) > mDmaHostAddressLimit) {
395 AllocSize = ALIGN_VALUE (Map->NumberOfBytes, mCpu->DmaBufferAlignment);
396 if (Map->Operation == MapOperationBusMasterWrite) {
397 mCpu->FlushDataCache (
398 mCpu,
399 (UINTN)Map->BufferAddress,
400 AllocSize,
401 EfiCpuFlushTypeInvalidate
402 );
403 CopyMem (
404 (VOID *)(UINTN)Map->HostAddress,
405 Map->BufferAddress,
406 Map->NumberOfBytes
407 );
408 }
409
410 FreePages (Map->BufferAddress, EFI_SIZE_TO_PAGES (AllocSize));
411 } else if (Map->DoubleBuffer) {
412 ASSERT (Map->Operation == MapOperationBusMasterWrite);
413
414 if (Map->Operation != MapOperationBusMasterWrite) {
415 Status = EFI_INVALID_PARAMETER;
416 } else {
417 Buffer = ALIGN_POINTER (Map->BufferAddress, mCpu->DmaBufferAlignment);
418
419 mCpu->FlushDataCache (
420 mCpu,
421 (UINTN)Buffer,
422 Map->NumberOfBytes,
423 EfiCpuFlushTypeInvalidate
424 );
425
426 CopyMem ((VOID *)(UINTN)Map->HostAddress, Buffer, Map->NumberOfBytes);
427
428 FreePool (Map->BufferAddress);
429 }
430 } else {
431 if (Map->Operation == MapOperationBusMasterWrite) {
432 //
433 // Make sure we read buffer from uncached memory and not the cache
434 //
435 mCpu->FlushDataCache (
436 mCpu,
437 Map->HostAddress,
438 Map->NumberOfBytes,
439 EfiCpuFlushTypeInvalidate
440 );
441 }
442 }
443
444 FreePool (Map);
445
446 return Status;
447}
448
449/**
450 Allocates pages that are suitable for an DmaMap() of type
451 MapOperationBusMasterCommonBuffer mapping.
452
453 @param MemoryType The type of memory to allocate,
454 EfiBootServicesData or EfiRuntimeServicesData.
455 @param Pages The number of pages to allocate.
456 @param HostAddress A pointer to store the base system memory
457 address of the allocated range.
458
459 @retval EFI_SUCCESS The requested memory pages were allocated.
460 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
461 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
462
463**/
464EFI_STATUS
465EFIAPI
466DmaAllocateBuffer (
467 IN EFI_MEMORY_TYPE MemoryType,
468 IN UINTN Pages,
469 OUT VOID **HostAddress
470 )
471{
472 return DmaAllocateAlignedBuffer (MemoryType, Pages, 0, HostAddress);
473}
474
475/**
476 Allocates pages that are suitable for an DmaMap() of type
477 MapOperationBusMasterCommonBuffer mapping, at the requested alignment.
478
479 @param MemoryType The type of memory to allocate,
480 EfiBootServicesData or EfiRuntimeServicesData.
481 @param Pages The number of pages to allocate.
482 @param Alignment Alignment in bytes of the base of the returned
483 buffer (must be a power of 2)
484 @param HostAddress A pointer to store the base system memory
485 address of the allocated range.
486
487 @retval EFI_SUCCESS The requested memory pages were allocated.
488 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
489 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
490
491**/
492EFI_STATUS
493EFIAPI
494DmaAllocateAlignedBuffer (
495 IN EFI_MEMORY_TYPE MemoryType,
496 IN UINTN Pages,
497 IN UINTN Alignment,
498 OUT VOID **HostAddress
499 )
500{
501 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
502 VOID *Allocation;
503 UINT64 Attributes;
504 UNCACHED_ALLOCATION *Alloc;
505 EFI_STATUS Status;
506
507 Attributes = EFI_MEMORY_XP;
508
509 if (Alignment == 0) {
510 Alignment = EFI_PAGE_SIZE;
511 }
512
513 if ((HostAddress == NULL) ||
514 ((Alignment & (Alignment - 1)) != 0))
515 {
516 return EFI_INVALID_PARAMETER;
517 }
518
519 if ((MemoryType == EfiBootServicesData) ||
520 (MemoryType == EfiRuntimeServicesData))
521 {
522 Allocation = InternalAllocateAlignedPages (MemoryType, Pages, Alignment);
523 } else {
524 return EFI_INVALID_PARAMETER;
525 }
526
527 if (Allocation == NULL) {
528 return EFI_OUT_OF_RESOURCES;
529 }
530
531 // Get the cacheability of the region
532 Status = gDS->GetMemorySpaceDescriptor ((UINTN)Allocation, &GcdDescriptor);
533 if (EFI_ERROR (Status)) {
534 goto FreeBuffer;
535 }
536
537 // Choose a suitable uncached memory type that is supported by the region
538 if (GcdDescriptor.Capabilities & EFI_MEMORY_WC) {
539 Attributes |= EFI_MEMORY_WC;
540 } else if (GcdDescriptor.Capabilities & EFI_MEMORY_UC) {
541 Attributes |= EFI_MEMORY_UC;
542 } else {
543 Status = EFI_UNSUPPORTED;
544 goto FreeBuffer;
545 }
546
547 Alloc = AllocatePool (sizeof *Alloc);
548 if (Alloc == NULL) {
549 goto FreeBuffer;
550 }
551
552 Alloc->HostAddress = Allocation;
553 Alloc->NumPages = Pages;
554 Alloc->Attributes = GcdDescriptor.Attributes;
555
556 InsertHeadList (&UncachedAllocationList, &Alloc->Link);
557
558 // Ensure that EFI_MEMORY_XP is in the capability set
559 if ((GcdDescriptor.Capabilities & EFI_MEMORY_XP) != EFI_MEMORY_XP) {
560 Status = gDS->SetMemorySpaceCapabilities (
561 (PHYSICAL_ADDRESS)(UINTN)Allocation,
562 EFI_PAGES_TO_SIZE (Pages),
563 GcdDescriptor.Capabilities | EFI_MEMORY_XP
564 );
565
566 // if we were to fail setting the capability, this would indicate an internal failure of the GCD code. We should
567 // assert here to let a platform know something went crazy, but for a release build we can let the allocation occur
568 // without the EFI_MEMORY_XP bit set, as that was the existing behavior
569 if (EFI_ERROR (Status)) {
570 DEBUG ((
571 DEBUG_ERROR,
572 "%a failed to set EFI_MEMORY_XP capability on 0x%llx for length 0x%llx. Attempting to allocate without XP set.\n",
573 __func__,
574 Allocation,
575 EFI_PAGES_TO_SIZE (Pages)
576 ));
577
578 ASSERT_EFI_ERROR (Status);
579
580 Attributes &= ~EFI_MEMORY_XP;
581 }
582 }
583
584 // Remap the region with the new attributes and mark it non-executable
585 Status = gDS->SetMemorySpaceAttributes (
586 (PHYSICAL_ADDRESS)(UINTN)Allocation,
587 EFI_PAGES_TO_SIZE (Pages),
588 Attributes
589 );
590 if (EFI_ERROR (Status)) {
591 goto FreeAlloc;
592 }
593
594 Status = mCpu->FlushDataCache (
595 mCpu,
596 (PHYSICAL_ADDRESS)(UINTN)Allocation,
597 EFI_PAGES_TO_SIZE (Pages),
598 EfiCpuFlushTypeInvalidate
599 );
600 if (EFI_ERROR (Status)) {
601 goto FreeAlloc;
602 }
603
604 *HostAddress = Allocation;
605
606 return EFI_SUCCESS;
607
608FreeAlloc:
609 RemoveEntryList (&Alloc->Link);
610 FreePool (Alloc);
611
612FreeBuffer:
613 FreePages (Allocation, Pages);
614 return Status;
615}
616
617/**
618 Frees memory that was allocated with DmaAllocateBuffer().
619
620 @param Pages The number of pages to free.
621 @param HostAddress The base system memory address of the allocated
622 range.
623
624 @retval EFI_SUCCESS The requested memory pages were freed.
625 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
626 Pages was not allocated with
627 DmaAllocateBuffer().
628
629**/
630EFI_STATUS
631EFIAPI
632DmaFreeBuffer (
633 IN UINTN Pages,
634 IN VOID *HostAddress
635 )
636{
637 LIST_ENTRY *Link;
638 UNCACHED_ALLOCATION *Alloc;
639 BOOLEAN Found;
640 EFI_STATUS Status;
641
642 if (HostAddress == NULL) {
643 return EFI_INVALID_PARAMETER;
644 }
645
646 for (Link = GetFirstNode (&UncachedAllocationList), Found = FALSE;
647 !IsNull (&UncachedAllocationList, Link);
648 Link = GetNextNode (&UncachedAllocationList, Link))
649 {
650 Alloc = BASE_CR (Link, UNCACHED_ALLOCATION, Link);
651 if ((Alloc->HostAddress == HostAddress) && (Alloc->NumPages == Pages)) {
652 Found = TRUE;
653 break;
654 }
655 }
656
657 if (!Found) {
658 ASSERT (FALSE);
659 return EFI_INVALID_PARAMETER;
660 }
661
662 RemoveEntryList (&Alloc->Link);
663
664 Status = gDS->SetMemorySpaceAttributes (
665 (PHYSICAL_ADDRESS)(UINTN)HostAddress,
666 EFI_PAGES_TO_SIZE (Pages),
667 Alloc->Attributes
668 );
669 if (EFI_ERROR (Status)) {
670 goto FreeAlloc;
671 }
672
673 //
674 // If we fail to restore the original attributes, it is better to leak the
675 // memory than to return it to the heap
676 //
677 FreePages (HostAddress, Pages);
678
679FreeAlloc:
680 FreePool (Alloc);
681 return Status;
682}
683
684EFI_STATUS
685EFIAPI
686NonCoherentDmaLibConstructor (
687 IN EFI_HANDLE ImageHandle,
688 IN EFI_SYSTEM_TABLE *SystemTable
689 )
690{
691 InitializeListHead (&UncachedAllocationList);
692
693 //
694 // Ensure that the combination of DMA addressing offset and limit produces
695 // a sane value.
696 //
697 ASSERT (PcdGet64 (PcdDmaDeviceLimit) > PcdGet64 (PcdDmaDeviceOffset));
698
699 mDmaHostAddressLimit = PcdGet64 (PcdDmaDeviceLimit) -
700 PcdGet64 (PcdDmaDeviceOffset);
701
702 // Get the Cpu protocol for later use
703 return gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
704}
Note: See TracBrowser for help on using the repository browser.

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