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
;
33 Initialize the RAM disk device node.
35 @param[in] PrivateData Points to RAM disk private data.
36 @param[in, out] RamDiskDevNode Points to the RAM disk device node.
40 RamDiskInitDeviceNode (
41 IN RAM_DISK_PRIVATE_DATA
*PrivateData
,
42 IN OUT MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
46 (UINT64
*)&(RamDiskDevNode
->StartingAddr
[0]),
47 (UINT64
)PrivateData
->StartingAddr
50 (UINT64
*)&(RamDiskDevNode
->EndingAddr
[0]),
51 (UINT64
)PrivateData
->StartingAddr
+ PrivateData
->Size
- 1
53 CopyGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
);
54 RamDiskDevNode
->Instance
= PrivateData
->InstanceNumber
;
58 Initialize and publish NVDIMM root device SSDT in ACPI table.
60 @retval EFI_SUCCESS The NVDIMM root device SSDT is published.
61 @retval Others The NVDIMM root device SSDT is not published.
70 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
71 UINTN SectionInstance
;
78 // Scan all the EFI raw section instances in FV to find the NVDIMM root
82 Status
= GetSectionFromFv (
89 if (EFI_ERROR (Status
)) {
93 if (Table
->OemTableId
== SIGNATURE_64 ('R', 'a', 'm', 'D', 'i', 's', 'k', ' ')) {
94 Status
= mAcpiTableProtocol
->InstallAcpiTable (
100 ASSERT_EFI_ERROR (Status
);
102 if (!EFI_ERROR (Status
)) {
103 mRamDiskSsdtTableKeyValid
= TRUE
;
118 Publish the RAM disk NVDIMM Firmware Interface Table (NFIT) to the ACPI
121 @param[in] PrivateData Points to RAM disk private data.
123 @retval EFI_SUCCESS The RAM disk NFIT has been published.
124 @retval others The RAM disk NFIT has not been published.
129 IN RAM_DISK_PRIVATE_DATA
*PrivateData
133 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
134 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
135 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
138 EFI_ACPI_TABLE_VERSION TableVersion
;
140 EFI_ACPI_DESCRIPTION_HEADER
*NfitHeader
;
141 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
147 UINTN DescriptorSize
;
148 UINT32 DescriptorVersion
;
154 // Get the EFI memory map.
160 Status
= gBS
->GetMemoryMap (
167 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
169 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)AllocatePool (MemoryMapSize
);
170 ASSERT (MemoryMap
!= NULL
);
171 Status
= gBS
->GetMemoryMap (
178 if (EFI_ERROR (Status
)) {
179 FreePool (MemoryMap
);
181 } while (Status
== EFI_BUFFER_TOO_SMALL
);
183 ASSERT_EFI_ERROR (Status
);
185 MemoryMapEntry
= MemoryMap
;
186 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ MemoryMapSize
);
187 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
188 if ((MemoryMapEntry
->Type
== EfiReservedMemoryType
) &&
189 (MemoryMapEntry
->PhysicalStart
<= PrivateData
->StartingAddr
) &&
190 (MemoryMapEntry
->PhysicalStart
+
191 MultU64x32 (MemoryMapEntry
->NumberOfPages
, EFI_PAGE_SIZE
)
192 >= PrivateData
->StartingAddr
+ PrivateData
->Size
))
197 "RamDiskPublishNfit: RAM disk with reserved memory type, will publish to NFIT.\n"
202 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
205 FreePool (MemoryMap
);
208 return EFI_NOT_FOUND
;
212 // Determine whether there is a NFIT already in the ACPI table.
214 Status
= EFI_SUCCESS
;
219 while (!EFI_ERROR (Status
)) {
220 Status
= mAcpiSdtProtocol
->GetAcpiTable (
222 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
226 if (!EFI_ERROR (Status
)) {
229 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
230 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
)
237 if (!EFI_ERROR (Status
)) {
239 // A NFIT is already in the ACPI table.
243 "RamDiskPublishNfit: A NFIT is already exist in the ACPI Table.\n"
246 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
;
247 NfitLen
= NfitHeader
->Length
+ sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
248 Nfit
= AllocateZeroPool (NfitLen
);
250 return EFI_OUT_OF_RESOURCES
;
253 CopyMem (Nfit
, TableHeader
, NfitHeader
->Length
);
256 // Update the NFIT head pointer.
258 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
261 // Uninstall the origin NFIT from the ACPI table.
263 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
267 ASSERT_EFI_ERROR (Status
);
269 if (EFI_ERROR (Status
)) {
275 // Append the System Physical Address (SPA) Range Structure at the end
276 // of the origin NFIT.
278 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
279 ((UINT8
*)Nfit
+ NfitHeader
->Length
);
282 // Update the length field of the NFIT
284 NfitHeader
->Length
= NfitLen
;
287 // The checksum will be updated after the new contents are appended.
289 NfitHeader
->Checksum
= 0;
292 // Assumption is made that if no NFIT is in the ACPI table, there is no
293 // NVDIMM root device in the \SB scope.
294 // Therefore, a NVDIMM root device will be reported via Secondary System
295 // Description Table (SSDT).
297 Status
= RamDiskPublishSsdt ();
298 if (EFI_ERROR (Status
)) {
303 // No NFIT is in the ACPI table, we will create one here.
307 "RamDiskPublishNfit: No NFIT is in the ACPI Table, will create one.\n"
310 NfitLen
= sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
) +
311 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
312 Nfit
= AllocateZeroPool (NfitLen
);
314 return EFI_OUT_OF_RESOURCES
;
317 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
318 ((UINT8
*)Nfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
320 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
321 NfitHeader
->Signature
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
;
322 NfitHeader
->Length
= NfitLen
;
323 NfitHeader
->Revision
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION
;
324 NfitHeader
->Checksum
= 0;
325 NfitHeader
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
326 NfitHeader
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
327 NfitHeader
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
328 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
329 CopyMem (NfitHeader
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (NfitHeader
->OemId
));
330 CopyMem (&NfitHeader
->OemTableId
, &CurrentData
, sizeof (UINT64
));
334 // Fill in the content of the SPA Range Structure.
336 SpaRange
->Type
= EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
;
337 SpaRange
->Length
= sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
338 SpaRange
->SystemPhysicalAddressRangeBase
= PrivateData
->StartingAddr
;
339 SpaRange
->SystemPhysicalAddressRangeLength
= PrivateData
->Size
;
340 CopyGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
);
342 Checksum
= CalculateCheckSum8 ((UINT8
*)Nfit
, NfitHeader
->Length
);
343 NfitHeader
->Checksum
= Checksum
;
346 // Publish the NFIT to the ACPI table.
347 // Note, since the NFIT might be modified by other driver, therefore, we
348 // do not track the returning TableKey from the InstallAcpiTable().
350 Status
= mAcpiTableProtocol
->InstallAcpiTable (
356 ASSERT_EFI_ERROR (Status
);
360 if (EFI_ERROR (Status
)) {
364 PrivateData
->InNfit
= TRUE
;
370 Unpublish the RAM disk NVDIMM Firmware Interface Table (NFIT) from the
373 @param[in] PrivateData Points to RAM disk private data.
375 @retval EFI_SUCCESS The RAM disk NFIT has been unpublished.
376 @retval others The RAM disk NFIT has not been unpublished.
380 RamDiskUnpublishNfit (
381 IN RAM_DISK_PRIVATE_DATA
*PrivateData
387 EFI_ACPI_TABLE_VERSION TableVersion
;
389 EFI_ACPI_DESCRIPTION_HEADER
*NewNfitHeader
;
390 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
394 EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*NfitStructHeader
;
400 // Find the NFIT in the ACPI table.
402 Status
= EFI_SUCCESS
;
407 while (!EFI_ERROR (Status
)) {
408 Status
= mAcpiSdtProtocol
->GetAcpiTable (
410 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
414 if (!EFI_ERROR (Status
)) {
417 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
418 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
)
425 if (EFI_ERROR (Status
)) {
427 // No NFIT is found in the ACPI table.
429 return EFI_NOT_FOUND
;
432 NewNfitLen
= ((EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
)->Length
-
433 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
436 // After removing this RAM disk from the NFIT, if no other structure is in
437 // the NFIT, we just remove the NFIT and the SSDT which is used to report
438 // the NVDIMM root device.
440 if (NewNfitLen
== sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
)) {
444 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
448 ASSERT_EFI_ERROR (Status
);
449 if (EFI_ERROR (Status
)) {
454 // Remove the SSDT which is used by RamDiskDxe driver to report the NVDIMM
456 // We do not care the return status since this SSDT might already be
457 // uninstalled by other drivers to update the information of the NVDIMM
460 if (mRamDiskSsdtTableKeyValid
) {
461 mRamDiskSsdtTableKeyValid
= FALSE
;
463 mAcpiTableProtocol
->UninstallAcpiTable (
472 NewNfit
= AllocateZeroPool (NewNfitLen
);
473 if (NewNfit
== NULL
) {
474 return EFI_OUT_OF_RESOURCES
;
478 // Get a copy of the old NFIT header content.
480 CopyMem (NewNfit
, TableHeader
, sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
481 NewNfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)NewNfit
;
482 NewNfitHeader
->Length
= NewNfitLen
;
483 NewNfitHeader
->Checksum
= 0;
486 // Copy the content of required NFIT structures.
488 NewNfitPtr
= (UINT8
*)NewNfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
489 RemainLen
= NewNfitLen
- sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
490 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
491 ((UINT8
*)TableHeader
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
492 while (RemainLen
> 0) {
493 if ((NfitStructHeader
->Type
== EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
) &&
494 (NfitStructHeader
->Length
== sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
)))
496 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)NfitStructHeader
;
498 if ((SpaRange
->SystemPhysicalAddressRangeBase
== PrivateData
->StartingAddr
) &&
499 (SpaRange
->SystemPhysicalAddressRangeLength
== PrivateData
->Size
) &&
500 (CompareGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
)))
503 // Skip the SPA Range Structure for the RAM disk to be unpublished
506 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
507 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
513 // Copy the content of origin NFIT.
515 CopyMem (NewNfitPtr
, NfitStructHeader
, NfitStructHeader
->Length
);
516 NewNfitPtr
= (UINT8
*)NewNfitPtr
+ NfitStructHeader
->Length
;
519 // Move to the header of next NFIT structure.
521 RemainLen
-= NfitStructHeader
->Length
;
522 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
523 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
526 Checksum
= CalculateCheckSum8 ((UINT8
*)NewNfit
, NewNfitHeader
->Length
);
527 NewNfitHeader
->Checksum
= Checksum
;
529 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
533 ASSERT_EFI_ERROR (Status
);
535 if (EFI_ERROR (Status
)) {
541 // Publish the NFIT to the ACPI table.
542 // Note, since the NFIT might be modified by other driver, therefore, we
543 // do not track the returning TableKey from the InstallAcpiTable().
545 Status
= mAcpiTableProtocol
->InstallAcpiTable (
551 ASSERT_EFI_ERROR (Status
);
554 if (EFI_ERROR (Status
)) {
562 Register a RAM disk with specified address, size and type.
564 @param[in] RamDiskBase The base address of registered RAM disk.
565 @param[in] RamDiskSize The size of registered RAM disk.
566 @param[in] RamDiskType The type of registered RAM disk. The GUID can be
567 any of the values defined in section 9.3.6.9, or a
569 @param[in] ParentDevicePath
570 Pointer to the parent device path. If there is no
571 parent device path then ParentDevicePath is NULL.
572 @param[out] DevicePath On return, points to a pointer to the device path
573 of the RAM disk device.
574 If ParentDevicePath is not NULL, the returned
575 DevicePath is created by appending a RAM disk node
576 to the parent device path. If ParentDevicePath is
577 NULL, the returned DevicePath is a RAM disk device
578 path without appending. This function is
579 responsible for allocating the buffer DevicePath
580 with the boot service AllocatePool().
582 @retval EFI_SUCCESS The RAM disk is registered successfully.
583 @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
585 @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
586 is already present in the handle database.
587 @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
594 IN UINT64 RamDiskBase
,
595 IN UINT64 RamDiskSize
,
596 IN EFI_GUID
*RamDiskType
,
597 IN EFI_DEVICE_PATH
*ParentDevicePath OPTIONAL
,
598 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
602 RAM_DISK_PRIVATE_DATA
*PrivateData
;
603 RAM_DISK_PRIVATE_DATA
*RegisteredPrivateData
;
604 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
605 UINTN DevicePathSize
;
608 if ((0 == RamDiskSize
) || (NULL
== RamDiskType
) || (NULL
== DevicePath
)) {
609 return EFI_INVALID_PARAMETER
;
613 // Add check to prevent data read across the memory boundary
615 if ((RamDiskSize
> MAX_UINTN
) ||
616 (RamDiskBase
> MAX_UINTN
- RamDiskSize
+ 1))
618 return EFI_INVALID_PARAMETER
;
621 RamDiskDevNode
= NULL
;
624 // Create a new RAM disk instance and initialize its private data
626 PrivateData
= AllocateCopyPool (
627 sizeof (RAM_DISK_PRIVATE_DATA
),
628 &mRamDiskPrivateDataTemplate
630 if (NULL
== PrivateData
) {
631 return EFI_OUT_OF_RESOURCES
;
634 PrivateData
->StartingAddr
= RamDiskBase
;
635 PrivateData
->Size
= RamDiskSize
;
636 CopyGuid (&PrivateData
->TypeGuid
, RamDiskType
);
637 InitializeListHead (&PrivateData
->ThisInstance
);
640 // Generate device path information for the registered RAM disk
642 RamDiskDevNode
= AllocateCopyPool (
643 sizeof (MEDIA_RAM_DISK_DEVICE_PATH
),
644 &mRamDiskDeviceNodeTemplate
646 if (NULL
== RamDiskDevNode
) {
647 Status
= EFI_OUT_OF_RESOURCES
;
651 RamDiskInitDeviceNode (PrivateData
, RamDiskDevNode
);
653 *DevicePath
= AppendDevicePathNode (
655 (EFI_DEVICE_PATH_PROTOCOL
*)RamDiskDevNode
657 if (NULL
== *DevicePath
) {
658 Status
= EFI_OUT_OF_RESOURCES
;
662 PrivateData
->DevicePath
= *DevicePath
;
665 // Check whether the created device path is already present in the handle
668 if (!IsListEmpty (&RegisteredRamDisks
)) {
669 DevicePathSize
= GetDevicePathSize (PrivateData
->DevicePath
);
671 BASE_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
672 RegisteredPrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
673 if (DevicePathSize
== GetDevicePathSize (RegisteredPrivateData
->DevicePath
)) {
675 // Compare device path
678 PrivateData
->DevicePath
,
679 RegisteredPrivateData
->DevicePath
,
684 Status
= EFI_ALREADY_STARTED
;
692 // Fill Block IO protocol informations for the RAM disk
694 RamDiskInitBlockIo (PrivateData
);
697 // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL on a new
700 Status
= gBS
->InstallMultipleProtocolInterfaces (
701 &PrivateData
->Handle
,
702 &gEfiBlockIoProtocolGuid
,
703 &PrivateData
->BlockIo
,
704 &gEfiBlockIo2ProtocolGuid
,
705 &PrivateData
->BlockIo2
,
706 &gEfiDevicePathProtocolGuid
,
707 PrivateData
->DevicePath
,
710 if (EFI_ERROR (Status
)) {
715 // Insert the newly created one to the registered RAM disk list
717 InsertTailList (&RegisteredRamDisks
, &PrivateData
->ThisInstance
);
719 gBS
->ConnectController (PrivateData
->Handle
, NULL
, NULL
, TRUE
);
721 FreePool (RamDiskDevNode
);
723 if ((mAcpiTableProtocol
!= NULL
) && (mAcpiSdtProtocol
!= NULL
)) {
724 RamDiskPublishNfit (PrivateData
);
730 if (RamDiskDevNode
!= NULL
) {
731 FreePool (RamDiskDevNode
);
734 if (PrivateData
!= NULL
) {
735 if (PrivateData
->DevicePath
) {
736 FreePool (PrivateData
->DevicePath
);
739 FreePool (PrivateData
);
746 Unregister a RAM disk specified by DevicePath.
748 @param[in] DevicePath A pointer to the device path that describes a RAM
751 @retval EFI_SUCCESS The RAM disk is unregistered successfully.
752 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
753 @retval EFI_UNSUPPORTED The device specified by DevicePath is not a
754 valid ramdisk device path and not supported
756 @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
763 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
767 LIST_ENTRY
*NextEntry
;
771 EFI_DEVICE_PATH_PROTOCOL
*Header
;
772 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
773 RAM_DISK_PRIVATE_DATA
*PrivateData
;
775 if (NULL
== DevicePath
) {
776 return EFI_INVALID_PARAMETER
;
780 // Locate the RAM disk device node.
782 RamDiskDevNode
= NULL
;
786 // Test if the current device node is a RAM disk.
788 if ((MEDIA_DEVICE_PATH
== Header
->Type
) &&
789 (MEDIA_RAM_DISK_DP
== Header
->SubType
))
791 RamDiskDevNode
= (MEDIA_RAM_DISK_DEVICE_PATH
*)Header
;
796 Header
= NextDevicePathNode (Header
);
797 } while ((Header
->Type
!= END_DEVICE_PATH_TYPE
));
799 if (NULL
== RamDiskDevNode
) {
800 return EFI_UNSUPPORTED
;
804 StartingAddr
= ReadUnaligned64 ((UINT64
*)&(RamDiskDevNode
->StartingAddr
[0]));
805 EndingAddr
= ReadUnaligned64 ((UINT64
*)&(RamDiskDevNode
->EndingAddr
[0]));
807 if (!IsListEmpty (&RegisteredRamDisks
)) {
808 BASE_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
809 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
812 // Unregister the RAM disk given by its starting address, ending address
815 if ((StartingAddr
== PrivateData
->StartingAddr
) &&
816 (EndingAddr
== PrivateData
->StartingAddr
+ PrivateData
->Size
- 1) &&
817 (CompareGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
)))
820 // Remove the content for this RAM disk in NFIT.
822 if (PrivateData
->InNfit
) {
823 RamDiskUnpublishNfit (PrivateData
);
827 // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL
829 gBS
->UninstallMultipleProtocolInterfaces (
831 &gEfiBlockIoProtocolGuid
,
832 &PrivateData
->BlockIo
,
833 &gEfiBlockIo2ProtocolGuid
,
834 &PrivateData
->BlockIo2
,
835 &gEfiDevicePathProtocolGuid
,
836 (EFI_DEVICE_PATH_PROTOCOL
*)PrivateData
->DevicePath
,
840 RemoveEntryList (&PrivateData
->ThisInstance
);
842 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
844 // If a RAM disk is created within HII, then the RamDiskDxe driver
845 // driver is responsible for freeing the allocated memory for the
848 FreePool ((VOID
*)(UINTN
)PrivateData
->StartingAddr
);
851 FreePool (PrivateData
->DevicePath
);
852 FreePool (PrivateData
);
863 return EFI_NOT_FOUND
;