2 The realization of EFI_RAM_DISK_PROTOCOL.
4 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 Copyright (c) Microsoft Corporation.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "RamDiskImpl.h"
13 RAM_DISK_PRIVATE_DATA mRamDiskPrivateDataTemplate
= {
14 RAM_DISK_PRIVATE_DATA_SIGNATURE
,
18 MEDIA_RAM_DISK_DEVICE_PATH mRamDiskDeviceNodeTemplate
= {
23 (UINT8
) (sizeof (MEDIA_RAM_DISK_DEVICE_PATH
)),
24 (UINT8
) ((sizeof (MEDIA_RAM_DISK_DEVICE_PATH
)) >> 8)
29 BOOLEAN mRamDiskSsdtTableKeyValid
= FALSE
;
30 UINTN mRamDiskSsdtTableKey
;
34 Initialize the RAM disk device node.
36 @param[in] PrivateData Points to RAM disk private data.
37 @param[in, out] RamDiskDevNode Points to the RAM disk device node.
41 RamDiskInitDeviceNode (
42 IN RAM_DISK_PRIVATE_DATA
*PrivateData
,
43 IN OUT MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
47 (UINT64
*) &(RamDiskDevNode
->StartingAddr
[0]),
48 (UINT64
) PrivateData
->StartingAddr
51 (UINT64
*) &(RamDiskDevNode
->EndingAddr
[0]),
52 (UINT64
) PrivateData
->StartingAddr
+ PrivateData
->Size
- 1
54 CopyGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
);
55 RamDiskDevNode
->Instance
= PrivateData
->InstanceNumber
;
60 Initialize and publish NVDIMM root device SSDT in ACPI table.
62 @retval EFI_SUCCESS The NVDIMM root device SSDT is published.
63 @retval Others The NVDIMM root device SSDT is not published.
72 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
73 UINTN SectionInstance
;
80 // Scan all the EFI raw section instances in FV to find the NVDIMM root
84 Status
= GetSectionFromFv (
91 if (EFI_ERROR (Status
)) {
95 if (Table
->OemTableId
== SIGNATURE_64 ('R', 'a', 'm', 'D', 'i', 's', 'k', ' ')) {
96 Status
= mAcpiTableProtocol
->InstallAcpiTable (
100 &mRamDiskSsdtTableKey
102 ASSERT_EFI_ERROR (Status
);
104 if (!EFI_ERROR (Status
)) {
105 mRamDiskSsdtTableKeyValid
= TRUE
;
121 Publish the RAM disk NVDIMM Firmware Interface Table (NFIT) to the ACPI
124 @param[in] PrivateData Points to RAM disk private data.
126 @retval EFI_SUCCESS The RAM disk NFIT has been published.
127 @retval others The RAM disk NFIT has not been published.
132 IN RAM_DISK_PRIVATE_DATA
*PrivateData
136 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
137 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
138 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
141 EFI_ACPI_TABLE_VERSION TableVersion
;
143 EFI_ACPI_DESCRIPTION_HEADER
*NfitHeader
;
144 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
150 UINTN DescriptorSize
;
151 UINT32 DescriptorVersion
;
157 // Get the EFI memory map.
163 Status
= gBS
->GetMemoryMap (
170 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
172 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*) AllocatePool (MemoryMapSize
);
173 ASSERT (MemoryMap
!= NULL
);
174 Status
= gBS
->GetMemoryMap (
181 if (EFI_ERROR (Status
)) {
182 FreePool (MemoryMap
);
184 } while (Status
== EFI_BUFFER_TOO_SMALL
);
185 ASSERT_EFI_ERROR (Status
);
187 MemoryMapEntry
= MemoryMap
;
188 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
189 while ((UINTN
) MemoryMapEntry
< (UINTN
) MemoryMapEnd
) {
190 if ((MemoryMapEntry
->Type
== EfiReservedMemoryType
) &&
191 (MemoryMapEntry
->PhysicalStart
<= PrivateData
->StartingAddr
) &&
192 (MemoryMapEntry
->PhysicalStart
+
193 MultU64x32 (MemoryMapEntry
->NumberOfPages
, EFI_PAGE_SIZE
)
194 >= PrivateData
->StartingAddr
+ PrivateData
->Size
)) {
198 "RamDiskPublishNfit: RAM disk with reserved meomry type, will publish to NFIT.\n"
202 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
204 FreePool (MemoryMap
);
207 return EFI_NOT_FOUND
;
211 // Determine whether there is a NFIT already in the ACPI table.
213 Status
= EFI_SUCCESS
;
218 while (!EFI_ERROR (Status
)) {
219 Status
= mAcpiSdtProtocol
->GetAcpiTable (
221 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
225 if (!EFI_ERROR (Status
)) {
228 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
229 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
235 if (!EFI_ERROR (Status
)) {
237 // A NFIT is already in the ACPI table.
241 "RamDiskPublishNfit: A NFIT is already exist in the ACPI Table.\n"
244 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
;
245 NfitLen
= NfitHeader
->Length
+ sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
246 Nfit
= AllocateZeroPool (NfitLen
);
248 return EFI_OUT_OF_RESOURCES
;
250 CopyMem (Nfit
, TableHeader
, NfitHeader
->Length
);
253 // Update the NFIT head pointer.
255 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
258 // Uninstall the origin NFIT from the ACPI table.
260 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
264 ASSERT_EFI_ERROR (Status
);
266 if (EFI_ERROR (Status
)) {
272 // Append the System Physical Address (SPA) Range Structure at the end
273 // of the origin NFIT.
275 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
276 ((UINT8
*)Nfit
+ NfitHeader
->Length
);
279 // Update the length field of the NFIT
281 NfitHeader
->Length
= NfitLen
;
284 // The checksum will be updated after the new contents are appended.
286 NfitHeader
->Checksum
= 0;
289 // Assumption is made that if no NFIT is in the ACPI table, there is no
290 // NVDIMM root device in the \SB scope.
291 // Therefore, a NVDIMM root device will be reported via Secondary System
292 // Description Table (SSDT).
294 Status
= RamDiskPublishSsdt ();
295 if (EFI_ERROR (Status
)) {
300 // No NFIT is in the ACPI table, we will create one here.
304 "RamDiskPublishNfit: No NFIT is in the ACPI Table, will create one.\n"
307 NfitLen
= sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
) +
308 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
309 Nfit
= AllocateZeroPool (NfitLen
);
311 return EFI_OUT_OF_RESOURCES
;
314 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
315 ((UINT8
*)Nfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
317 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
318 NfitHeader
->Signature
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
;
319 NfitHeader
->Length
= NfitLen
;
320 NfitHeader
->Revision
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION
;
321 NfitHeader
->Checksum
= 0;
322 NfitHeader
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
323 NfitHeader
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
324 NfitHeader
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
325 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
326 CopyMem (NfitHeader
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (NfitHeader
->OemId
));
327 CopyMem (&NfitHeader
->OemTableId
, &CurrentData
, sizeof (UINT64
));
331 // Fill in the content of the SPA Range Structure.
333 SpaRange
->Type
= EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
;
334 SpaRange
->Length
= sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
335 SpaRange
->SystemPhysicalAddressRangeBase
= PrivateData
->StartingAddr
;
336 SpaRange
->SystemPhysicalAddressRangeLength
= PrivateData
->Size
;
337 CopyGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
);
339 Checksum
= CalculateCheckSum8((UINT8
*)Nfit
, NfitHeader
->Length
);
340 NfitHeader
->Checksum
= Checksum
;
343 // Publish the NFIT to the ACPI table.
344 // Note, since the NFIT might be modified by other driver, therefore, we
345 // do not track the returning TableKey from the InstallAcpiTable().
347 Status
= mAcpiTableProtocol
->InstallAcpiTable (
353 ASSERT_EFI_ERROR (Status
);
357 if (EFI_ERROR (Status
)) {
361 PrivateData
->InNfit
= TRUE
;
368 Unpublish the RAM disk NVDIMM Firmware Interface Table (NFIT) from the
371 @param[in] PrivateData Points to RAM disk private data.
373 @retval EFI_SUCCESS The RAM disk NFIT has been unpublished.
374 @retval others The RAM disk NFIT has not been unpublished.
378 RamDiskUnpublishNfit (
379 IN RAM_DISK_PRIVATE_DATA
*PrivateData
385 EFI_ACPI_TABLE_VERSION TableVersion
;
387 EFI_ACPI_DESCRIPTION_HEADER
*NewNfitHeader
;
388 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
392 EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*NfitStructHeader
;
398 // Find the NFIT in the ACPI table.
400 Status
= EFI_SUCCESS
;
405 while (!EFI_ERROR (Status
)) {
406 Status
= mAcpiSdtProtocol
->GetAcpiTable (
408 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
412 if (!EFI_ERROR (Status
)) {
415 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
416 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
422 if (EFI_ERROR (Status
)) {
424 // No NFIT is found in the ACPI table.
426 return EFI_NOT_FOUND
;
429 NewNfitLen
= ((EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
)->Length
-
430 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
433 // After removing this RAM disk from the NFIT, if no other structure is in
434 // the NFIT, we just remove the NFIT and the SSDT which is used to report
435 // the NVDIMM root device.
437 if (NewNfitLen
== sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
)) {
441 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
445 ASSERT_EFI_ERROR (Status
);
446 if (EFI_ERROR (Status
)) {
451 // Remove the SSDT which is used by RamDiskDxe driver to report the NVDIMM
453 // We do not care the return status since this SSDT might already be
454 // uninstalled by other drivers to update the information of the NVDIMM
457 if (mRamDiskSsdtTableKeyValid
) {
458 mRamDiskSsdtTableKeyValid
= FALSE
;
460 mAcpiTableProtocol
->UninstallAcpiTable (
469 NewNfit
= AllocateZeroPool (NewNfitLen
);
470 if (NewNfit
== NULL
) {
471 return EFI_OUT_OF_RESOURCES
;
475 // Get a copy of the old NFIT header content.
477 CopyMem (NewNfit
, TableHeader
, sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
478 NewNfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)NewNfit
;
479 NewNfitHeader
->Length
= NewNfitLen
;
480 NewNfitHeader
->Checksum
= 0;
483 // Copy the content of required NFIT structures.
485 NewNfitPtr
= (UINT8
*)NewNfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
486 RemainLen
= NewNfitLen
- sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
487 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
488 ((UINT8
*)TableHeader
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
489 while (RemainLen
> 0) {
490 if ((NfitStructHeader
->Type
== EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
) &&
491 (NfitStructHeader
->Length
== sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
))) {
492 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)NfitStructHeader
;
494 if ((SpaRange
->SystemPhysicalAddressRangeBase
== PrivateData
->StartingAddr
) &&
495 (SpaRange
->SystemPhysicalAddressRangeLength
== PrivateData
->Size
) &&
496 (CompareGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
))) {
498 // Skip the SPA Range Structure for the RAM disk to be unpublished
501 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
502 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
508 // Copy the content of origin NFIT.
510 CopyMem (NewNfitPtr
, NfitStructHeader
, NfitStructHeader
->Length
);
511 NewNfitPtr
= (UINT8
*)NewNfitPtr
+ NfitStructHeader
->Length
;
514 // Move to the header of next NFIT structure.
516 RemainLen
-= NfitStructHeader
->Length
;
517 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
518 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
521 Checksum
= CalculateCheckSum8((UINT8
*)NewNfit
, NewNfitHeader
->Length
);
522 NewNfitHeader
->Checksum
= Checksum
;
524 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
528 ASSERT_EFI_ERROR (Status
);
530 if (EFI_ERROR (Status
)) {
536 // Publish the NFIT to the ACPI table.
537 // Note, since the NFIT might be modified by other driver, therefore, we
538 // do not track the returning TableKey from the InstallAcpiTable().
540 Status
= mAcpiTableProtocol
->InstallAcpiTable (
546 ASSERT_EFI_ERROR (Status
);
549 if (EFI_ERROR (Status
)) {
558 Register a RAM disk with specified address, size and type.
560 @param[in] RamDiskBase The base address of registered RAM disk.
561 @param[in] RamDiskSize The size of registered RAM disk.
562 @param[in] RamDiskType The type of registered RAM disk. The GUID can be
563 any of the values defined in section 9.3.6.9, or a
565 @param[in] ParentDevicePath
566 Pointer to the parent device path. If there is no
567 parent device path then ParentDevicePath is NULL.
568 @param[out] DevicePath On return, points to a pointer to the device path
569 of the RAM disk device.
570 If ParentDevicePath is not NULL, the returned
571 DevicePath is created by appending a RAM disk node
572 to the parent device path. If ParentDevicePath is
573 NULL, the returned DevicePath is a RAM disk device
574 path without appending. This function is
575 responsible for allocating the buffer DevicePath
576 with the boot service AllocatePool().
578 @retval EFI_SUCCESS The RAM disk is registered successfully.
579 @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
581 @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
582 is already present in the handle database.
583 @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
590 IN UINT64 RamDiskBase
,
591 IN UINT64 RamDiskSize
,
592 IN EFI_GUID
*RamDiskType
,
593 IN EFI_DEVICE_PATH
*ParentDevicePath OPTIONAL
,
594 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
598 RAM_DISK_PRIVATE_DATA
*PrivateData
;
599 RAM_DISK_PRIVATE_DATA
*RegisteredPrivateData
;
600 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
601 UINTN DevicePathSize
;
604 if ((0 == RamDiskSize
) || (NULL
== RamDiskType
) || (NULL
== DevicePath
)) {
605 return EFI_INVALID_PARAMETER
;
609 // Add check to prevent data read across the memory boundary
611 if ((RamDiskSize
> MAX_UINTN
) ||
612 (RamDiskBase
> MAX_UINTN
- RamDiskSize
+ 1)) {
613 return EFI_INVALID_PARAMETER
;
616 RamDiskDevNode
= NULL
;
619 // Create a new RAM disk instance and initialize its private data
621 PrivateData
= AllocateCopyPool (
622 sizeof (RAM_DISK_PRIVATE_DATA
),
623 &mRamDiskPrivateDataTemplate
625 if (NULL
== PrivateData
) {
626 return EFI_OUT_OF_RESOURCES
;
629 PrivateData
->StartingAddr
= RamDiskBase
;
630 PrivateData
->Size
= RamDiskSize
;
631 CopyGuid (&PrivateData
->TypeGuid
, RamDiskType
);
632 InitializeListHead (&PrivateData
->ThisInstance
);
635 // Generate device path information for the registered RAM disk
637 RamDiskDevNode
= AllocateCopyPool (
638 sizeof (MEDIA_RAM_DISK_DEVICE_PATH
),
639 &mRamDiskDeviceNodeTemplate
641 if (NULL
== RamDiskDevNode
) {
642 Status
= EFI_OUT_OF_RESOURCES
;
646 RamDiskInitDeviceNode (PrivateData
, RamDiskDevNode
);
648 *DevicePath
= AppendDevicePathNode (
650 (EFI_DEVICE_PATH_PROTOCOL
*) RamDiskDevNode
652 if (NULL
== *DevicePath
) {
653 Status
= EFI_OUT_OF_RESOURCES
;
657 PrivateData
->DevicePath
= *DevicePath
;
660 // Check whether the created device path is already present in the handle
663 if (!IsListEmpty(&RegisteredRamDisks
)) {
664 DevicePathSize
= GetDevicePathSize (PrivateData
->DevicePath
);
666 BASE_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
667 RegisteredPrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
668 if (DevicePathSize
== GetDevicePathSize (RegisteredPrivateData
->DevicePath
)) {
670 // Compare device path
673 PrivateData
->DevicePath
,
674 RegisteredPrivateData
->DevicePath
,
675 DevicePathSize
)) == 0) {
677 Status
= EFI_ALREADY_STARTED
;
685 // Fill Block IO protocol informations for the RAM disk
687 RamDiskInitBlockIo (PrivateData
);
690 // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL on a new
693 Status
= gBS
->InstallMultipleProtocolInterfaces (
694 &PrivateData
->Handle
,
695 &gEfiBlockIoProtocolGuid
,
696 &PrivateData
->BlockIo
,
697 &gEfiBlockIo2ProtocolGuid
,
698 &PrivateData
->BlockIo2
,
699 &gEfiDevicePathProtocolGuid
,
700 PrivateData
->DevicePath
,
703 if (EFI_ERROR (Status
)) {
708 // Insert the newly created one to the registered RAM disk list
710 InsertTailList (&RegisteredRamDisks
, &PrivateData
->ThisInstance
);
712 gBS
->ConnectController (PrivateData
->Handle
, NULL
, NULL
, TRUE
);
714 FreePool (RamDiskDevNode
);
716 if ((mAcpiTableProtocol
!= NULL
) && (mAcpiSdtProtocol
!= NULL
)) {
717 RamDiskPublishNfit (PrivateData
);
723 if (RamDiskDevNode
!= NULL
) {
724 FreePool (RamDiskDevNode
);
727 if (PrivateData
!= NULL
) {
728 if (PrivateData
->DevicePath
) {
729 FreePool (PrivateData
->DevicePath
);
732 FreePool (PrivateData
);
740 Unregister a RAM disk specified by DevicePath.
742 @param[in] DevicePath A pointer to the device path that describes a RAM
745 @retval EFI_SUCCESS The RAM disk is unregistered successfully.
746 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
747 @retval EFI_UNSUPPORTED The device specified by DevicePath is not a
748 valid ramdisk device path and not supported
750 @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
757 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
761 LIST_ENTRY
*NextEntry
;
765 EFI_DEVICE_PATH_PROTOCOL
*Header
;
766 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
767 RAM_DISK_PRIVATE_DATA
*PrivateData
;
769 if (NULL
== DevicePath
) {
770 return EFI_INVALID_PARAMETER
;
774 // Locate the RAM disk device node.
776 RamDiskDevNode
= NULL
;
780 // Test if the current device node is a RAM disk.
782 if ((MEDIA_DEVICE_PATH
== Header
->Type
) &&
783 (MEDIA_RAM_DISK_DP
== Header
->SubType
)) {
784 RamDiskDevNode
= (MEDIA_RAM_DISK_DEVICE_PATH
*) Header
;
789 Header
= NextDevicePathNode (Header
);
790 } while ((Header
->Type
!= END_DEVICE_PATH_TYPE
));
792 if (NULL
== RamDiskDevNode
) {
793 return EFI_UNSUPPORTED
;
797 StartingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->StartingAddr
[0]));
798 EndingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->EndingAddr
[0]));
800 if (!IsListEmpty(&RegisteredRamDisks
)) {
801 BASE_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
802 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
805 // Unregister the RAM disk given by its starting address, ending address
808 if ((StartingAddr
== PrivateData
->StartingAddr
) &&
809 (EndingAddr
== PrivateData
->StartingAddr
+ PrivateData
->Size
- 1) &&
810 (CompareGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
))) {
812 // Remove the content for this RAM disk in NFIT.
814 if (PrivateData
->InNfit
) {
815 RamDiskUnpublishNfit (PrivateData
);
819 // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL
821 gBS
->UninstallMultipleProtocolInterfaces (
823 &gEfiBlockIoProtocolGuid
,
824 &PrivateData
->BlockIo
,
825 &gEfiBlockIo2ProtocolGuid
,
826 &PrivateData
->BlockIo2
,
827 &gEfiDevicePathProtocolGuid
,
828 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
832 RemoveEntryList (&PrivateData
->ThisInstance
);
834 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
836 // If a RAM disk is created within HII, then the RamDiskDxe driver
837 // driver is responsible for freeing the allocated memory for the
840 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
843 FreePool (PrivateData
->DevicePath
);
844 FreePool (PrivateData
);
855 return EFI_NOT_FOUND
;