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 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "RamDiskImpl.h"
18 RAM_DISK_PRIVATE_DATA mRamDiskPrivateDataTemplate
= {
19 RAM_DISK_PRIVATE_DATA_SIGNATURE
,
23 MEDIA_RAM_DISK_DEVICE_PATH mRamDiskDeviceNodeTemplate
= {
28 (UINT8
) (sizeof (MEDIA_RAM_DISK_DEVICE_PATH
)),
29 (UINT8
) ((sizeof (MEDIA_RAM_DISK_DEVICE_PATH
)) >> 8)
34 BOOLEAN mRamDiskSsdtTableKeyValid
= FALSE
;
35 UINTN mRamDiskSsdtTableKey
;
39 Initialize the RAM disk device node.
41 @param[in] PrivateData Points to RAM disk private data.
42 @param[in, out] RamDiskDevNode Points to the RAM disk device node.
46 RamDiskInitDeviceNode (
47 IN RAM_DISK_PRIVATE_DATA
*PrivateData
,
48 IN OUT MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
52 (UINT64
*) &(RamDiskDevNode
->StartingAddr
[0]),
53 (UINT64
) PrivateData
->StartingAddr
56 (UINT64
*) &(RamDiskDevNode
->EndingAddr
[0]),
57 (UINT64
) PrivateData
->StartingAddr
+ PrivateData
->Size
- 1
59 CopyGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
);
60 RamDiskDevNode
->Instance
= PrivateData
->InstanceNumber
;
65 Initialize and publish NVDIMM root device SSDT in ACPI table.
67 @retval EFI_SUCCESS The NVDIMM root device SSDT is published.
68 @retval Others The NVDIMM root device SSDT is not published.
77 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
78 UINTN SectionInstance
;
85 // Scan all the EFI raw section instances in FV to find the NVDIMM root
89 Status
= GetSectionFromFv (
96 if (EFI_ERROR (Status
)) {
100 if (Table
->OemTableId
== SIGNATURE_64 ('R', 'a', 'm', 'D', 'i', 's', 'k', ' ')) {
101 Status
= mAcpiTableProtocol
->InstallAcpiTable (
105 &mRamDiskSsdtTableKey
107 ASSERT_EFI_ERROR (Status
);
109 if (!EFI_ERROR (Status
)) {
110 mRamDiskSsdtTableKeyValid
= TRUE
;
126 Publish the RAM disk NVDIMM Firmware Interface Table (NFIT) to the ACPI
129 @param[in] PrivateData Points to RAM disk private data.
131 @retval EFI_SUCCESS The RAM disk NFIT has been published.
132 @retval others The RAM disk NFIT has not been published.
137 IN RAM_DISK_PRIVATE_DATA
*PrivateData
141 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
142 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
143 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
146 EFI_ACPI_TABLE_VERSION TableVersion
;
148 EFI_ACPI_DESCRIPTION_HEADER
*NfitHeader
;
149 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
155 UINTN DescriptorSize
;
156 UINT32 DescriptorVersion
;
162 // Get the EFI memory map.
168 Status
= gBS
->GetMemoryMap (
175 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
177 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*) AllocatePool (MemoryMapSize
);
178 ASSERT (MemoryMap
!= NULL
);
179 Status
= gBS
->GetMemoryMap (
186 if (EFI_ERROR (Status
)) {
187 FreePool (MemoryMap
);
189 } while (Status
== EFI_BUFFER_TOO_SMALL
);
190 ASSERT_EFI_ERROR (Status
);
192 MemoryMapEntry
= MemoryMap
;
193 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
194 while ((UINTN
) MemoryMapEntry
< (UINTN
) MemoryMapEnd
) {
195 if ((MemoryMapEntry
->Type
== EfiReservedMemoryType
) &&
196 (MemoryMapEntry
->PhysicalStart
<= PrivateData
->StartingAddr
) &&
197 (MemoryMapEntry
->PhysicalStart
+
198 MultU64x32 (MemoryMapEntry
->NumberOfPages
, EFI_PAGE_SIZE
)
199 >= PrivateData
->StartingAddr
+ PrivateData
->Size
)) {
203 "RamDiskPublishNfit: RAM disk with reserved meomry type, will publish to NFIT.\n"
207 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
209 FreePool (MemoryMap
);
212 return EFI_NOT_FOUND
;
216 // Determine whether there is a NFIT already in the ACPI table.
218 Status
= EFI_SUCCESS
;
223 while (!EFI_ERROR (Status
)) {
224 Status
= mAcpiSdtProtocol
->GetAcpiTable (
226 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
230 if (!EFI_ERROR (Status
)) {
233 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
234 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
240 if (!EFI_ERROR (Status
)) {
242 // A NFIT is already in the ACPI table.
246 "RamDiskPublishNfit: A NFIT is already exist in the ACPI Table.\n"
249 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
;
250 NfitLen
= NfitHeader
->Length
+ sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
251 Nfit
= AllocateZeroPool (NfitLen
);
253 return EFI_OUT_OF_RESOURCES
;
255 CopyMem (Nfit
, TableHeader
, NfitHeader
->Length
);
258 // Update the NFIT head pointer.
260 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
263 // Uninstall the origin NFIT from the ACPI table.
265 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
269 ASSERT_EFI_ERROR (Status
);
271 if (EFI_ERROR (Status
)) {
277 // Append the System Physical Address (SPA) Range Structure at the end
278 // of the origin NFIT.
280 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
281 ((UINT8
*)Nfit
+ NfitHeader
->Length
);
284 // Update the length field of the NFIT
286 NfitHeader
->Length
= NfitLen
;
289 // The checksum will be updated after the new contents are appended.
291 NfitHeader
->Checksum
= 0;
294 // Assumption is made that if no NFIT is in the ACPI table, there is no
295 // NVDIMM root device in the \SB scope.
296 // Therefore, a NVDIMM root device will be reported via Secondary System
297 // Description Table (SSDT).
299 Status
= RamDiskPublishSsdt ();
300 if (EFI_ERROR (Status
)) {
305 // No NFIT is in the ACPI table, we will create one here.
309 "RamDiskPublishNfit: No NFIT is in the ACPI Table, will create one.\n"
312 NfitLen
= sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
) +
313 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
314 Nfit
= AllocateZeroPool (NfitLen
);
316 return EFI_OUT_OF_RESOURCES
;
319 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
320 ((UINT8
*)Nfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
322 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
323 NfitHeader
->Signature
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
;
324 NfitHeader
->Length
= NfitLen
;
325 NfitHeader
->Revision
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION
;
326 NfitHeader
->Checksum
= 0;
327 NfitHeader
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
328 NfitHeader
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
329 NfitHeader
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
330 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
331 CopyMem (NfitHeader
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (NfitHeader
->OemId
));
332 CopyMem (&NfitHeader
->OemTableId
, &CurrentData
, sizeof (UINT64
));
336 // Fill in the content of the SPA Range Structure.
338 SpaRange
->Type
= EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
;
339 SpaRange
->Length
= sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
340 SpaRange
->SystemPhysicalAddressRangeBase
= PrivateData
->StartingAddr
;
341 SpaRange
->SystemPhysicalAddressRangeLength
= PrivateData
->Size
;
342 CopyGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
);
344 Checksum
= CalculateCheckSum8((UINT8
*)Nfit
, NfitHeader
->Length
);
345 NfitHeader
->Checksum
= Checksum
;
348 // Publish the NFIT to the ACPI table.
349 // Note, since the NFIT might be modified by other driver, therefore, we
350 // do not track the returning TableKey from the InstallAcpiTable().
352 Status
= mAcpiTableProtocol
->InstallAcpiTable (
358 ASSERT_EFI_ERROR (Status
);
362 if (EFI_ERROR (Status
)) {
366 PrivateData
->InNfit
= TRUE
;
373 Unpublish the RAM disk NVDIMM Firmware Interface Table (NFIT) from the
376 @param[in] PrivateData Points to RAM disk private data.
378 @retval EFI_SUCCESS The RAM disk NFIT has been unpublished.
379 @retval others The RAM disk NFIT has not been unpublished.
383 RamDiskUnpublishNfit (
384 IN RAM_DISK_PRIVATE_DATA
*PrivateData
390 EFI_ACPI_TABLE_VERSION TableVersion
;
392 EFI_ACPI_DESCRIPTION_HEADER
*NewNfitHeader
;
393 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
397 EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*NfitStructHeader
;
403 // Find the NFIT in the ACPI table.
405 Status
= EFI_SUCCESS
;
410 while (!EFI_ERROR (Status
)) {
411 Status
= mAcpiSdtProtocol
->GetAcpiTable (
413 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
417 if (!EFI_ERROR (Status
)) {
420 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
421 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
427 if (EFI_ERROR (Status
)) {
429 // No NFIT is found in the ACPI table.
431 return EFI_NOT_FOUND
;
434 NewNfitLen
= ((EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
)->Length
-
435 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
438 // After removing this RAM disk from the NFIT, if no other structure is in
439 // the NFIT, we just remove the NFIT and the SSDT which is used to report
440 // the NVDIMM root device.
442 if (NewNfitLen
== sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
)) {
446 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
450 ASSERT_EFI_ERROR (Status
);
451 if (EFI_ERROR (Status
)) {
456 // Remove the SSDT which is used by RamDiskDxe driver to report the NVDIMM
458 // We do not care the return status since this SSDT might already be
459 // uninstalled by other drivers to update the information of the NVDIMM
462 if (mRamDiskSsdtTableKeyValid
) {
463 mRamDiskSsdtTableKeyValid
= FALSE
;
465 mAcpiTableProtocol
->UninstallAcpiTable (
474 NewNfit
= AllocateZeroPool (NewNfitLen
);
475 if (NewNfit
== NULL
) {
476 return EFI_OUT_OF_RESOURCES
;
480 // Get a copy of the old NFIT header content.
482 CopyMem (NewNfit
, TableHeader
, sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
483 NewNfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)NewNfit
;
484 NewNfitHeader
->Length
= NewNfitLen
;
485 NewNfitHeader
->Checksum
= 0;
488 // Copy the content of required NFIT structures.
490 NewNfitPtr
= (UINT8
*)NewNfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
491 RemainLen
= NewNfitLen
- sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
492 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
493 ((UINT8
*)TableHeader
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
494 while (RemainLen
> 0) {
495 if ((NfitStructHeader
->Type
== EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
) &&
496 (NfitStructHeader
->Length
== sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
))) {
497 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)NfitStructHeader
;
499 if ((SpaRange
->SystemPhysicalAddressRangeBase
== PrivateData
->StartingAddr
) &&
500 (SpaRange
->SystemPhysicalAddressRangeLength
== PrivateData
->Size
) &&
501 (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
)) {
563 Register a RAM disk with specified address, size and type.
565 @param[in] RamDiskBase The base address of registered RAM disk.
566 @param[in] RamDiskSize The size of registered RAM disk.
567 @param[in] RamDiskType The type of registered RAM disk. The GUID can be
568 any of the values defined in section 9.3.6.9, or a
570 @param[in] ParentDevicePath
571 Pointer to the parent device path. If there is no
572 parent device path then ParentDevicePath is NULL.
573 @param[out] DevicePath On return, points to a pointer to the device path
574 of the RAM disk device.
575 If ParentDevicePath is not NULL, the returned
576 DevicePath is created by appending a RAM disk node
577 to the parent device path. If ParentDevicePath is
578 NULL, the returned DevicePath is a RAM disk device
579 path without appending. This function is
580 responsible for allocating the buffer DevicePath
581 with the boot service AllocatePool().
583 @retval EFI_SUCCESS The RAM disk is registered successfully.
584 @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
586 @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
587 is already present in the handle database.
588 @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
595 IN UINT64 RamDiskBase
,
596 IN UINT64 RamDiskSize
,
597 IN EFI_GUID
*RamDiskType
,
598 IN EFI_DEVICE_PATH
*ParentDevicePath OPTIONAL
,
599 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
603 RAM_DISK_PRIVATE_DATA
*PrivateData
;
604 RAM_DISK_PRIVATE_DATA
*RegisteredPrivateData
;
605 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
606 UINTN DevicePathSize
;
609 if ((0 == RamDiskSize
) || (NULL
== RamDiskType
) || (NULL
== DevicePath
)) {
610 return EFI_INVALID_PARAMETER
;
614 // Add check to prevent data read across the memory boundary
616 if ((RamDiskSize
> MAX_UINTN
) ||
617 (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 EFI_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
,
680 DevicePathSize
)) == 0) {
682 Status
= EFI_ALREADY_STARTED
;
690 // Fill Block IO protocol informations for the RAM disk
692 RamDiskInitBlockIo (PrivateData
);
695 // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL on a new
698 Status
= gBS
->InstallMultipleProtocolInterfaces (
699 &PrivateData
->Handle
,
700 &gEfiBlockIoProtocolGuid
,
701 &PrivateData
->BlockIo
,
702 &gEfiBlockIo2ProtocolGuid
,
703 &PrivateData
->BlockIo2
,
704 &gEfiDevicePathProtocolGuid
,
705 PrivateData
->DevicePath
,
708 if (EFI_ERROR (Status
)) {
713 // Insert the newly created one to the registered RAM disk list
715 InsertTailList (&RegisteredRamDisks
, &PrivateData
->ThisInstance
);
717 gBS
->ConnectController (PrivateData
->Handle
, NULL
, NULL
, TRUE
);
719 FreePool (RamDiskDevNode
);
721 if ((mAcpiTableProtocol
!= NULL
) && (mAcpiSdtProtocol
!= NULL
)) {
722 RamDiskPublishNfit (PrivateData
);
728 if (RamDiskDevNode
!= NULL
) {
729 FreePool (RamDiskDevNode
);
732 if (PrivateData
!= NULL
) {
733 if (PrivateData
->DevicePath
) {
734 FreePool (PrivateData
->DevicePath
);
737 FreePool (PrivateData
);
745 Unregister a RAM disk specified by DevicePath.
747 @param[in] DevicePath A pointer to the device path that describes a RAM
750 @retval EFI_SUCCESS The RAM disk is unregistered successfully.
751 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
752 @retval EFI_UNSUPPORTED The device specified by DevicePath is not a
753 valid ramdisk device path and not supported
755 @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
762 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
766 LIST_ENTRY
*NextEntry
;
770 EFI_DEVICE_PATH_PROTOCOL
*Header
;
771 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
772 RAM_DISK_PRIVATE_DATA
*PrivateData
;
774 if (NULL
== DevicePath
) {
775 return EFI_INVALID_PARAMETER
;
779 // Locate the RAM disk device node.
781 RamDiskDevNode
= NULL
;
785 // Test if the current device node is a RAM disk.
787 if ((MEDIA_DEVICE_PATH
== Header
->Type
) &&
788 (MEDIA_RAM_DISK_DP
== Header
->SubType
)) {
789 RamDiskDevNode
= (MEDIA_RAM_DISK_DEVICE_PATH
*) Header
;
794 Header
= NextDevicePathNode (Header
);
795 } while ((Header
->Type
!= END_DEVICE_PATH_TYPE
));
797 if (NULL
== RamDiskDevNode
) {
798 return EFI_UNSUPPORTED
;
802 StartingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->StartingAddr
[0]));
803 EndingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->EndingAddr
[0]));
805 if (!IsListEmpty(&RegisteredRamDisks
)) {
806 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
807 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
810 // Unregister the RAM disk given by its starting address, ending address
813 if ((StartingAddr
== PrivateData
->StartingAddr
) &&
814 (EndingAddr
== PrivateData
->StartingAddr
+ PrivateData
->Size
- 1) &&
815 (CompareGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
))) {
817 // Remove the content for this RAM disk in NFIT.
819 if (PrivateData
->InNfit
) {
820 RamDiskUnpublishNfit (PrivateData
);
824 // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL
826 gBS
->UninstallMultipleProtocolInterfaces (
828 &gEfiBlockIoProtocolGuid
,
829 &PrivateData
->BlockIo
,
830 &gEfiBlockIo2ProtocolGuid
,
831 &PrivateData
->BlockIo2
,
832 &gEfiDevicePathProtocolGuid
,
833 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
837 RemoveEntryList (&PrivateData
->ThisInstance
);
839 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
841 // If a RAM disk is created within HII, then the RamDiskDxe driver
842 // driver is responsible for freeing the allocated memory for the
845 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
848 FreePool (PrivateData
->DevicePath
);
849 FreePool (PrivateData
);
860 return EFI_NOT_FOUND
;