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 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "RamDiskImpl.h"
12 RAM_DISK_PRIVATE_DATA mRamDiskPrivateDataTemplate
= {
13 RAM_DISK_PRIVATE_DATA_SIGNATURE
,
17 MEDIA_RAM_DISK_DEVICE_PATH mRamDiskDeviceNodeTemplate
= {
22 (UINT8
) (sizeof (MEDIA_RAM_DISK_DEVICE_PATH
)),
23 (UINT8
) ((sizeof (MEDIA_RAM_DISK_DEVICE_PATH
)) >> 8)
28 BOOLEAN mRamDiskSsdtTableKeyValid
= FALSE
;
29 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
;
59 Initialize and publish NVDIMM root device SSDT in ACPI table.
61 @retval EFI_SUCCESS The NVDIMM root device SSDT is published.
62 @retval Others The NVDIMM root device SSDT is not published.
71 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
72 UINTN SectionInstance
;
79 // Scan all the EFI raw section instances in FV to find the NVDIMM root
83 Status
= GetSectionFromFv (
90 if (EFI_ERROR (Status
)) {
94 if (Table
->OemTableId
== SIGNATURE_64 ('R', 'a', 'm', 'D', 'i', 's', 'k', ' ')) {
95 Status
= mAcpiTableProtocol
->InstallAcpiTable (
101 ASSERT_EFI_ERROR (Status
);
103 if (!EFI_ERROR (Status
)) {
104 mRamDiskSsdtTableKeyValid
= TRUE
;
120 Publish the RAM disk NVDIMM Firmware Interface Table (NFIT) to the ACPI
123 @param[in] PrivateData Points to RAM disk private data.
125 @retval EFI_SUCCESS The RAM disk NFIT has been published.
126 @retval others The RAM disk NFIT has not been published.
131 IN RAM_DISK_PRIVATE_DATA
*PrivateData
135 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
136 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
137 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
140 EFI_ACPI_TABLE_VERSION TableVersion
;
142 EFI_ACPI_DESCRIPTION_HEADER
*NfitHeader
;
143 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
149 UINTN DescriptorSize
;
150 UINT32 DescriptorVersion
;
156 // Get the EFI memory map.
162 Status
= gBS
->GetMemoryMap (
169 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
171 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*) AllocatePool (MemoryMapSize
);
172 ASSERT (MemoryMap
!= NULL
);
173 Status
= gBS
->GetMemoryMap (
180 if (EFI_ERROR (Status
)) {
181 FreePool (MemoryMap
);
183 } while (Status
== EFI_BUFFER_TOO_SMALL
);
184 ASSERT_EFI_ERROR (Status
);
186 MemoryMapEntry
= MemoryMap
;
187 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
188 while ((UINTN
) MemoryMapEntry
< (UINTN
) MemoryMapEnd
) {
189 if ((MemoryMapEntry
->Type
== EfiReservedMemoryType
) &&
190 (MemoryMapEntry
->PhysicalStart
<= PrivateData
->StartingAddr
) &&
191 (MemoryMapEntry
->PhysicalStart
+
192 MultU64x32 (MemoryMapEntry
->NumberOfPages
, EFI_PAGE_SIZE
)
193 >= PrivateData
->StartingAddr
+ PrivateData
->Size
)) {
197 "RamDiskPublishNfit: RAM disk with reserved meomry type, will publish to NFIT.\n"
201 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
203 FreePool (MemoryMap
);
206 return EFI_NOT_FOUND
;
210 // Determine whether there is a NFIT already in the ACPI table.
212 Status
= EFI_SUCCESS
;
217 while (!EFI_ERROR (Status
)) {
218 Status
= mAcpiSdtProtocol
->GetAcpiTable (
220 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
224 if (!EFI_ERROR (Status
)) {
227 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
228 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
234 if (!EFI_ERROR (Status
)) {
236 // A NFIT is already in the ACPI table.
240 "RamDiskPublishNfit: A NFIT is already exist in the ACPI Table.\n"
243 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
;
244 NfitLen
= NfitHeader
->Length
+ sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
245 Nfit
= AllocateZeroPool (NfitLen
);
247 return EFI_OUT_OF_RESOURCES
;
249 CopyMem (Nfit
, TableHeader
, NfitHeader
->Length
);
252 // Update the NFIT head pointer.
254 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
257 // Uninstall the origin NFIT from the ACPI table.
259 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
263 ASSERT_EFI_ERROR (Status
);
265 if (EFI_ERROR (Status
)) {
271 // Append the System Physical Address (SPA) Range Structure at the end
272 // of the origin NFIT.
274 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
275 ((UINT8
*)Nfit
+ NfitHeader
->Length
);
278 // Update the length field of the NFIT
280 NfitHeader
->Length
= NfitLen
;
283 // The checksum will be updated after the new contents are appended.
285 NfitHeader
->Checksum
= 0;
288 // Assumption is made that if no NFIT is in the ACPI table, there is no
289 // NVDIMM root device in the \SB scope.
290 // Therefore, a NVDIMM root device will be reported via Secondary System
291 // Description Table (SSDT).
293 Status
= RamDiskPublishSsdt ();
294 if (EFI_ERROR (Status
)) {
299 // No NFIT is in the ACPI table, we will create one here.
303 "RamDiskPublishNfit: No NFIT is in the ACPI Table, will create one.\n"
306 NfitLen
= sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
) +
307 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
308 Nfit
= AllocateZeroPool (NfitLen
);
310 return EFI_OUT_OF_RESOURCES
;
313 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
314 ((UINT8
*)Nfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
316 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
317 NfitHeader
->Signature
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
;
318 NfitHeader
->Length
= NfitLen
;
319 NfitHeader
->Revision
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION
;
320 NfitHeader
->Checksum
= 0;
321 NfitHeader
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
322 NfitHeader
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
323 NfitHeader
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
324 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
325 CopyMem (NfitHeader
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (NfitHeader
->OemId
));
326 CopyMem (&NfitHeader
->OemTableId
, &CurrentData
, sizeof (UINT64
));
330 // Fill in the content of the SPA Range Structure.
332 SpaRange
->Type
= EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
;
333 SpaRange
->Length
= sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
334 SpaRange
->SystemPhysicalAddressRangeBase
= PrivateData
->StartingAddr
;
335 SpaRange
->SystemPhysicalAddressRangeLength
= PrivateData
->Size
;
336 CopyGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
);
338 Checksum
= CalculateCheckSum8((UINT8
*)Nfit
, NfitHeader
->Length
);
339 NfitHeader
->Checksum
= Checksum
;
342 // Publish the NFIT to the ACPI table.
343 // Note, since the NFIT might be modified by other driver, therefore, we
344 // do not track the returning TableKey from the InstallAcpiTable().
346 Status
= mAcpiTableProtocol
->InstallAcpiTable (
352 ASSERT_EFI_ERROR (Status
);
356 if (EFI_ERROR (Status
)) {
360 PrivateData
->InNfit
= TRUE
;
367 Unpublish the RAM disk NVDIMM Firmware Interface Table (NFIT) from the
370 @param[in] PrivateData Points to RAM disk private data.
372 @retval EFI_SUCCESS The RAM disk NFIT has been unpublished.
373 @retval others The RAM disk NFIT has not been unpublished.
377 RamDiskUnpublishNfit (
378 IN RAM_DISK_PRIVATE_DATA
*PrivateData
384 EFI_ACPI_TABLE_VERSION TableVersion
;
386 EFI_ACPI_DESCRIPTION_HEADER
*NewNfitHeader
;
387 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
391 EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*NfitStructHeader
;
397 // Find the NFIT in the ACPI table.
399 Status
= EFI_SUCCESS
;
404 while (!EFI_ERROR (Status
)) {
405 Status
= mAcpiSdtProtocol
->GetAcpiTable (
407 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
411 if (!EFI_ERROR (Status
)) {
414 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
415 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
421 if (EFI_ERROR (Status
)) {
423 // No NFIT is found in the ACPI table.
425 return EFI_NOT_FOUND
;
428 NewNfitLen
= ((EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
)->Length
-
429 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
432 // After removing this RAM disk from the NFIT, if no other structure is in
433 // the NFIT, we just remove the NFIT and the SSDT which is used to report
434 // the NVDIMM root device.
436 if (NewNfitLen
== sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
)) {
440 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
444 ASSERT_EFI_ERROR (Status
);
445 if (EFI_ERROR (Status
)) {
450 // Remove the SSDT which is used by RamDiskDxe driver to report the NVDIMM
452 // We do not care the return status since this SSDT might already be
453 // uninstalled by other drivers to update the information of the NVDIMM
456 if (mRamDiskSsdtTableKeyValid
) {
457 mRamDiskSsdtTableKeyValid
= FALSE
;
459 mAcpiTableProtocol
->UninstallAcpiTable (
468 NewNfit
= AllocateZeroPool (NewNfitLen
);
469 if (NewNfit
== NULL
) {
470 return EFI_OUT_OF_RESOURCES
;
474 // Get a copy of the old NFIT header content.
476 CopyMem (NewNfit
, TableHeader
, sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
477 NewNfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)NewNfit
;
478 NewNfitHeader
->Length
= NewNfitLen
;
479 NewNfitHeader
->Checksum
= 0;
482 // Copy the content of required NFIT structures.
484 NewNfitPtr
= (UINT8
*)NewNfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
485 RemainLen
= NewNfitLen
- sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
486 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
487 ((UINT8
*)TableHeader
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
488 while (RemainLen
> 0) {
489 if ((NfitStructHeader
->Type
== EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
) &&
490 (NfitStructHeader
->Length
== sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
))) {
491 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)NfitStructHeader
;
493 if ((SpaRange
->SystemPhysicalAddressRangeBase
== PrivateData
->StartingAddr
) &&
494 (SpaRange
->SystemPhysicalAddressRangeLength
== PrivateData
->Size
) &&
495 (CompareGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
))) {
497 // Skip the SPA Range Structure for the RAM disk to be unpublished
500 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
501 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
507 // Copy the content of origin NFIT.
509 CopyMem (NewNfitPtr
, NfitStructHeader
, NfitStructHeader
->Length
);
510 NewNfitPtr
= (UINT8
*)NewNfitPtr
+ NfitStructHeader
->Length
;
513 // Move to the header of next NFIT structure.
515 RemainLen
-= NfitStructHeader
->Length
;
516 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
517 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
520 Checksum
= CalculateCheckSum8((UINT8
*)NewNfit
, NewNfitHeader
->Length
);
521 NewNfitHeader
->Checksum
= Checksum
;
523 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
527 ASSERT_EFI_ERROR (Status
);
529 if (EFI_ERROR (Status
)) {
535 // Publish the NFIT to the ACPI table.
536 // Note, since the NFIT might be modified by other driver, therefore, we
537 // do not track the returning TableKey from the InstallAcpiTable().
539 Status
= mAcpiTableProtocol
->InstallAcpiTable (
545 ASSERT_EFI_ERROR (Status
);
548 if (EFI_ERROR (Status
)) {
557 Register a RAM disk with specified address, size and type.
559 @param[in] RamDiskBase The base address of registered RAM disk.
560 @param[in] RamDiskSize The size of registered RAM disk.
561 @param[in] RamDiskType The type of registered RAM disk. The GUID can be
562 any of the values defined in section 9.3.6.9, or a
564 @param[in] ParentDevicePath
565 Pointer to the parent device path. If there is no
566 parent device path then ParentDevicePath is NULL.
567 @param[out] DevicePath On return, points to a pointer to the device path
568 of the RAM disk device.
569 If ParentDevicePath is not NULL, the returned
570 DevicePath is created by appending a RAM disk node
571 to the parent device path. If ParentDevicePath is
572 NULL, the returned DevicePath is a RAM disk device
573 path without appending. This function is
574 responsible for allocating the buffer DevicePath
575 with the boot service AllocatePool().
577 @retval EFI_SUCCESS The RAM disk is registered successfully.
578 @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
580 @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
581 is already present in the handle database.
582 @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
589 IN UINT64 RamDiskBase
,
590 IN UINT64 RamDiskSize
,
591 IN EFI_GUID
*RamDiskType
,
592 IN EFI_DEVICE_PATH
*ParentDevicePath OPTIONAL
,
593 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
597 RAM_DISK_PRIVATE_DATA
*PrivateData
;
598 RAM_DISK_PRIVATE_DATA
*RegisteredPrivateData
;
599 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
600 UINTN DevicePathSize
;
603 if ((0 == RamDiskSize
) || (NULL
== RamDiskType
) || (NULL
== DevicePath
)) {
604 return EFI_INVALID_PARAMETER
;
608 // Add check to prevent data read across the memory boundary
610 if ((RamDiskSize
> MAX_UINTN
) ||
611 (RamDiskBase
> MAX_UINTN
- RamDiskSize
+ 1)) {
612 return EFI_INVALID_PARAMETER
;
615 RamDiskDevNode
= NULL
;
618 // Create a new RAM disk instance and initialize its private data
620 PrivateData
= AllocateCopyPool (
621 sizeof (RAM_DISK_PRIVATE_DATA
),
622 &mRamDiskPrivateDataTemplate
624 if (NULL
== PrivateData
) {
625 return EFI_OUT_OF_RESOURCES
;
628 PrivateData
->StartingAddr
= RamDiskBase
;
629 PrivateData
->Size
= RamDiskSize
;
630 CopyGuid (&PrivateData
->TypeGuid
, RamDiskType
);
631 InitializeListHead (&PrivateData
->ThisInstance
);
634 // Generate device path information for the registered RAM disk
636 RamDiskDevNode
= AllocateCopyPool (
637 sizeof (MEDIA_RAM_DISK_DEVICE_PATH
),
638 &mRamDiskDeviceNodeTemplate
640 if (NULL
== RamDiskDevNode
) {
641 Status
= EFI_OUT_OF_RESOURCES
;
645 RamDiskInitDeviceNode (PrivateData
, RamDiskDevNode
);
647 *DevicePath
= AppendDevicePathNode (
649 (EFI_DEVICE_PATH_PROTOCOL
*) RamDiskDevNode
651 if (NULL
== *DevicePath
) {
652 Status
= EFI_OUT_OF_RESOURCES
;
656 PrivateData
->DevicePath
= *DevicePath
;
659 // Check whether the created device path is already present in the handle
662 if (!IsListEmpty(&RegisteredRamDisks
)) {
663 DevicePathSize
= GetDevicePathSize (PrivateData
->DevicePath
);
665 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
666 RegisteredPrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
667 if (DevicePathSize
== GetDevicePathSize (RegisteredPrivateData
->DevicePath
)) {
669 // Compare device path
672 PrivateData
->DevicePath
,
673 RegisteredPrivateData
->DevicePath
,
674 DevicePathSize
)) == 0) {
676 Status
= EFI_ALREADY_STARTED
;
684 // Fill Block IO protocol informations for the RAM disk
686 RamDiskInitBlockIo (PrivateData
);
689 // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL on a new
692 Status
= gBS
->InstallMultipleProtocolInterfaces (
693 &PrivateData
->Handle
,
694 &gEfiBlockIoProtocolGuid
,
695 &PrivateData
->BlockIo
,
696 &gEfiBlockIo2ProtocolGuid
,
697 &PrivateData
->BlockIo2
,
698 &gEfiDevicePathProtocolGuid
,
699 PrivateData
->DevicePath
,
702 if (EFI_ERROR (Status
)) {
707 // Insert the newly created one to the registered RAM disk list
709 InsertTailList (&RegisteredRamDisks
, &PrivateData
->ThisInstance
);
711 gBS
->ConnectController (PrivateData
->Handle
, NULL
, NULL
, TRUE
);
713 FreePool (RamDiskDevNode
);
715 if ((mAcpiTableProtocol
!= NULL
) && (mAcpiSdtProtocol
!= NULL
)) {
716 RamDiskPublishNfit (PrivateData
);
722 if (RamDiskDevNode
!= NULL
) {
723 FreePool (RamDiskDevNode
);
726 if (PrivateData
!= NULL
) {
727 if (PrivateData
->DevicePath
) {
728 FreePool (PrivateData
->DevicePath
);
731 FreePool (PrivateData
);
739 Unregister a RAM disk specified by DevicePath.
741 @param[in] DevicePath A pointer to the device path that describes a RAM
744 @retval EFI_SUCCESS The RAM disk is unregistered successfully.
745 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
746 @retval EFI_UNSUPPORTED The device specified by DevicePath is not a
747 valid ramdisk device path and not supported
749 @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
756 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
760 LIST_ENTRY
*NextEntry
;
764 EFI_DEVICE_PATH_PROTOCOL
*Header
;
765 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
766 RAM_DISK_PRIVATE_DATA
*PrivateData
;
768 if (NULL
== DevicePath
) {
769 return EFI_INVALID_PARAMETER
;
773 // Locate the RAM disk device node.
775 RamDiskDevNode
= NULL
;
779 // Test if the current device node is a RAM disk.
781 if ((MEDIA_DEVICE_PATH
== Header
->Type
) &&
782 (MEDIA_RAM_DISK_DP
== Header
->SubType
)) {
783 RamDiskDevNode
= (MEDIA_RAM_DISK_DEVICE_PATH
*) Header
;
788 Header
= NextDevicePathNode (Header
);
789 } while ((Header
->Type
!= END_DEVICE_PATH_TYPE
));
791 if (NULL
== RamDiskDevNode
) {
792 return EFI_UNSUPPORTED
;
796 StartingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->StartingAddr
[0]));
797 EndingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->EndingAddr
[0]));
799 if (!IsListEmpty(&RegisteredRamDisks
)) {
800 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
801 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
804 // Unregister the RAM disk given by its starting address, ending address
807 if ((StartingAddr
== PrivateData
->StartingAddr
) &&
808 (EndingAddr
== PrivateData
->StartingAddr
+ PrivateData
->Size
- 1) &&
809 (CompareGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
))) {
811 // Remove the content for this RAM disk in NFIT.
813 if (PrivateData
->InNfit
) {
814 RamDiskUnpublishNfit (PrivateData
);
818 // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL
820 gBS
->UninstallMultipleProtocolInterfaces (
822 &gEfiBlockIoProtocolGuid
,
823 &PrivateData
->BlockIo
,
824 &gEfiBlockIo2ProtocolGuid
,
825 &PrivateData
->BlockIo2
,
826 &gEfiDevicePathProtocolGuid
,
827 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
831 RemoveEntryList (&PrivateData
->ThisInstance
);
833 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
835 // If a RAM disk is created within HII, then the RamDiskDxe driver
836 // driver is responsible for freeing the allocated memory for the
839 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
842 FreePool (PrivateData
->DevicePath
);
843 FreePool (PrivateData
);
854 return EFI_NOT_FOUND
;