2 The realization of EFI_RAM_DISK_PROTOCOL.
4 Copyright (c) 2016, 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
;
80 Status
= GetSectionFromFv (
87 ASSERT_EFI_ERROR (Status
);
89 ASSERT (Table
->OemTableId
== SIGNATURE_64 ('R', 'a', 'm', 'D', 'i', 's', 'k', ' '));
91 Status
= mAcpiTableProtocol
->InstallAcpiTable (
97 ASSERT_EFI_ERROR (Status
);
99 if (!EFI_ERROR (Status
)) {
100 mRamDiskSsdtTableKeyValid
= TRUE
;
102 mRamDiskSsdtTableKeyValid
= FALSE
;
112 Publish the RAM disk NVDIMM Firmware Interface Table (NFIT) to the ACPI
115 @param[in] PrivateData Points to RAM disk private data.
117 @retval EFI_SUCCESS The RAM disk NFIT has been published.
118 @retval others The RAM disk NFIT has not been published.
123 IN RAM_DISK_PRIVATE_DATA
*PrivateData
127 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
128 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
129 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
132 EFI_ACPI_TABLE_VERSION TableVersion
;
134 EFI_ACPI_DESCRIPTION_HEADER
*NfitHeader
;
135 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
141 UINTN DescriptorSize
;
142 UINT32 DescriptorVersion
;
148 // Get the EFI memory map.
154 Status
= gBS
->GetMemoryMap (
161 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
163 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*) AllocatePool (MemoryMapSize
);
164 ASSERT (MemoryMap
!= NULL
);
165 Status
= gBS
->GetMemoryMap (
172 if (EFI_ERROR (Status
)) {
173 FreePool (MemoryMap
);
175 } while (Status
== EFI_BUFFER_TOO_SMALL
);
176 ASSERT_EFI_ERROR (Status
);
178 MemoryMapEntry
= MemoryMap
;
179 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
180 while ((UINTN
) MemoryMapEntry
< (UINTN
) MemoryMapEnd
) {
181 if ((MemoryMapEntry
->Type
== EfiReservedMemoryType
) &&
182 (MemoryMapEntry
->PhysicalStart
<= PrivateData
->StartingAddr
) &&
183 (MemoryMapEntry
->PhysicalStart
+
184 MultU64x32 (MemoryMapEntry
->NumberOfPages
, EFI_PAGE_SIZE
)
185 >= PrivateData
->StartingAddr
+ PrivateData
->Size
)) {
189 "RamDiskPublishNfit: RAM disk with reserved meomry type, will publish to NFIT.\n"
193 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
195 FreePool (MemoryMap
);
198 return EFI_NOT_FOUND
;
202 // Determine whether there is a NFIT already in the ACPI table.
204 Status
= EFI_SUCCESS
;
209 while (!EFI_ERROR (Status
)) {
210 Status
= mAcpiSdtProtocol
->GetAcpiTable (
212 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
216 if (!EFI_ERROR (Status
)) {
219 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
220 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
226 if (!EFI_ERROR (Status
)) {
228 // A NFIT is already in the ACPI table.
232 "RamDiskPublishNfit: A NFIT is already exist in the ACPI Table.\n"
235 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
;
236 NfitLen
= NfitHeader
->Length
+ sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
237 Nfit
= AllocateZeroPool (NfitLen
);
239 return EFI_OUT_OF_RESOURCES
;
241 CopyMem (Nfit
, TableHeader
, NfitHeader
->Length
);
244 // Update the NFIT head pointer.
246 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
249 // Uninstall the origin NFIT from the ACPI table.
251 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
255 ASSERT_EFI_ERROR (Status
);
257 if (EFI_ERROR (Status
)) {
263 // Append the System Physical Address (SPA) Range Structure at the end
264 // of the origin NFIT.
266 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
267 ((UINT8
*)Nfit
+ NfitHeader
->Length
);
270 // Update the length field of the NFIT
272 NfitHeader
->Length
= NfitLen
;
275 // The checksum will be updated after the new contents are appended.
277 NfitHeader
->Checksum
= 0;
280 // Assumption is made that if no NFIT is in the ACPI table, there is no
281 // NVDIMM root device in the \SB scope.
282 // Therefore, a NVDIMM root device will be reported via Secondary System
283 // Description Table (SSDT).
285 Status
= RamDiskPublishSsdt ();
286 if (EFI_ERROR (Status
)) {
291 // No NFIT is in the ACPI table, we will create one here.
295 "RamDiskPublishNfit: No NFIT is in the ACPI Table, will create one.\n"
298 NfitLen
= sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
) +
299 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
300 Nfit
= AllocateZeroPool (NfitLen
);
302 return EFI_OUT_OF_RESOURCES
;
305 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
306 ((UINT8
*)Nfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
308 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
309 NfitHeader
->Signature
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
;
310 NfitHeader
->Length
= NfitLen
;
311 NfitHeader
->Revision
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION
;
312 NfitHeader
->Checksum
= 0;
313 NfitHeader
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
314 NfitHeader
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
315 NfitHeader
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
316 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
317 CopyMem (NfitHeader
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (NfitHeader
->OemId
));
318 CopyMem (&NfitHeader
->OemTableId
, &CurrentData
, sizeof (UINT64
));
322 // Fill in the content of the SPA Range Structure.
324 SpaRange
->Type
= EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
;
325 SpaRange
->Length
= sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
326 SpaRange
->SystemPhysicalAddressRangeBase
= PrivateData
->StartingAddr
;
327 SpaRange
->SystemPhysicalAddressRangeLength
= PrivateData
->Size
;
328 CopyGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
);
330 Checksum
= CalculateCheckSum8((UINT8
*)Nfit
, NfitHeader
->Length
);
331 NfitHeader
->Checksum
= Checksum
;
334 // Publish the NFIT to the ACPI table.
335 // Note, since the NFIT might be modified by other driver, therefore, we
336 // do not track the returning TableKey from the InstallAcpiTable().
338 Status
= mAcpiTableProtocol
->InstallAcpiTable (
344 ASSERT_EFI_ERROR (Status
);
348 if (EFI_ERROR (Status
)) {
352 PrivateData
->InNfit
= TRUE
;
359 Unpublish the RAM disk NVDIMM Firmware Interface Table (NFIT) from the
362 @param[in] PrivateData Points to RAM disk private data.
364 @retval EFI_SUCCESS The RAM disk NFIT has been unpublished.
365 @retval others The RAM disk NFIT has not been unpublished.
369 RamDiskUnpublishNfit (
370 IN RAM_DISK_PRIVATE_DATA
*PrivateData
376 EFI_ACPI_TABLE_VERSION TableVersion
;
378 EFI_ACPI_DESCRIPTION_HEADER
*NewNfitHeader
;
379 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
383 EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*NfitStructHeader
;
389 // Find the NFIT in the ACPI table.
391 Status
= EFI_SUCCESS
;
396 while (!EFI_ERROR (Status
)) {
397 Status
= mAcpiSdtProtocol
->GetAcpiTable (
399 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
403 if (!EFI_ERROR (Status
)) {
406 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
407 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
413 if (EFI_ERROR (Status
)) {
415 // No NFIT is found in the ACPI table.
417 return EFI_NOT_FOUND
;
420 NewNfitLen
= ((EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
)->Length
-
421 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
424 // After removing this RAM disk from the NFIT, if no other structure is in
425 // the NFIT, we just remove the NFIT and the SSDT which is used to report
426 // the NVDIMM root device.
428 if (NewNfitLen
== sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
)) {
432 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
436 ASSERT_EFI_ERROR (Status
);
437 if (EFI_ERROR (Status
)) {
442 // Remove the SSDT which is used by RamDiskDxe driver to report the NVDIMM
444 // We do not care the return status since this SSDT might already be
445 // uninstalled by other drivers to update the information of the NVDIMM
448 if (mRamDiskSsdtTableKeyValid
) {
449 mRamDiskSsdtTableKeyValid
= FALSE
;
451 mAcpiTableProtocol
->UninstallAcpiTable (
460 NewNfit
= AllocateZeroPool (NewNfitLen
);
461 if (NewNfit
== NULL
) {
462 return EFI_OUT_OF_RESOURCES
;
466 // Get a copy of the old NFIT header content.
468 CopyMem (NewNfit
, TableHeader
, sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
469 NewNfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)NewNfit
;
470 NewNfitHeader
->Length
= NewNfitLen
;
471 NewNfitHeader
->Checksum
= 0;
474 // Copy the content of required NFIT structures.
476 NewNfitPtr
= (UINT8
*)NewNfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
477 RemainLen
= NewNfitLen
- sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
478 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
479 ((UINT8
*)TableHeader
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
480 while (RemainLen
> 0) {
481 if ((NfitStructHeader
->Type
== EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
) &&
482 (NfitStructHeader
->Length
== sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
))) {
483 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)NfitStructHeader
;
485 if ((SpaRange
->SystemPhysicalAddressRangeBase
== PrivateData
->StartingAddr
) &&
486 (SpaRange
->SystemPhysicalAddressRangeLength
== PrivateData
->Size
) &&
487 (CompareGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
))) {
489 // Skip the SPA Range Structure for the RAM disk to be unpublished
492 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
493 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
499 // Copy the content of origin NFIT.
501 CopyMem (NewNfitPtr
, NfitStructHeader
, NfitStructHeader
->Length
);
502 NewNfitPtr
= (UINT8
*)NewNfitPtr
+ NfitStructHeader
->Length
;
505 // Move to the header of next NFIT structure.
507 RemainLen
-= NfitStructHeader
->Length
;
508 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
509 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
512 Checksum
= CalculateCheckSum8((UINT8
*)NewNfit
, NewNfitHeader
->Length
);
513 NewNfitHeader
->Checksum
= Checksum
;
515 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
519 ASSERT_EFI_ERROR (Status
);
521 if (EFI_ERROR (Status
)) {
527 // Publish the NFIT to the ACPI table.
528 // Note, since the NFIT might be modified by other driver, therefore, we
529 // do not track the returning TableKey from the InstallAcpiTable().
531 Status
= mAcpiTableProtocol
->InstallAcpiTable (
537 ASSERT_EFI_ERROR (Status
);
540 if (EFI_ERROR (Status
)) {
549 Register a RAM disk with specified address, size and type.
551 @param[in] RamDiskBase The base address of registered RAM disk.
552 @param[in] RamDiskSize The size of registered RAM disk.
553 @param[in] RamDiskType The type of registered RAM disk. The GUID can be
554 any of the values defined in section 9.3.6.9, or a
556 @param[in] ParentDevicePath
557 Pointer to the parent device path. If there is no
558 parent device path then ParentDevicePath is NULL.
559 @param[out] DevicePath On return, points to a pointer to the device path
560 of the RAM disk device.
561 If ParentDevicePath is not NULL, the returned
562 DevicePath is created by appending a RAM disk node
563 to the parent device path. If ParentDevicePath is
564 NULL, the returned DevicePath is a RAM disk device
565 path without appending. This function is
566 responsible for allocating the buffer DevicePath
567 with the boot service AllocatePool().
569 @retval EFI_SUCCESS The RAM disk is registered successfully.
570 @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
572 @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
573 is already present in the handle database.
574 @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
581 IN UINT64 RamDiskBase
,
582 IN UINT64 RamDiskSize
,
583 IN EFI_GUID
*RamDiskType
,
584 IN EFI_DEVICE_PATH
*ParentDevicePath OPTIONAL
,
585 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
589 RAM_DISK_PRIVATE_DATA
*PrivateData
;
590 RAM_DISK_PRIVATE_DATA
*RegisteredPrivateData
;
591 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
592 UINTN DevicePathSize
;
595 if ((0 == RamDiskSize
) || (NULL
== RamDiskType
) || (NULL
== DevicePath
)) {
596 return EFI_INVALID_PARAMETER
;
600 // Add check to prevent data read across the memory boundary
602 if (RamDiskBase
+ RamDiskSize
> ((UINTN
) -1) - RAM_DISK_BLOCK_SIZE
+ 1) {
603 return EFI_INVALID_PARAMETER
;
606 RamDiskDevNode
= NULL
;
609 // Create a new RAM disk instance and initialize its private data
611 PrivateData
= AllocateCopyPool (
612 sizeof (RAM_DISK_PRIVATE_DATA
),
613 &mRamDiskPrivateDataTemplate
615 if (NULL
== PrivateData
) {
616 return EFI_OUT_OF_RESOURCES
;
619 PrivateData
->StartingAddr
= RamDiskBase
;
620 PrivateData
->Size
= RamDiskSize
;
621 CopyGuid (&PrivateData
->TypeGuid
, RamDiskType
);
622 InitializeListHead (&PrivateData
->ThisInstance
);
625 // Generate device path information for the registered RAM disk
627 RamDiskDevNode
= AllocateCopyPool (
628 sizeof (MEDIA_RAM_DISK_DEVICE_PATH
),
629 &mRamDiskDeviceNodeTemplate
631 if (NULL
== RamDiskDevNode
) {
632 Status
= EFI_OUT_OF_RESOURCES
;
636 RamDiskInitDeviceNode (PrivateData
, RamDiskDevNode
);
638 *DevicePath
= AppendDevicePathNode (
640 (EFI_DEVICE_PATH_PROTOCOL
*) RamDiskDevNode
642 if (NULL
== *DevicePath
) {
643 Status
= EFI_OUT_OF_RESOURCES
;
647 PrivateData
->DevicePath
= *DevicePath
;
650 // Check whether the created device path is already present in the handle
653 if (!IsListEmpty(&RegisteredRamDisks
)) {
654 DevicePathSize
= GetDevicePathSize (PrivateData
->DevicePath
);
656 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
657 RegisteredPrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
658 if (DevicePathSize
== GetDevicePathSize (RegisteredPrivateData
->DevicePath
)) {
660 // Compare device path
663 PrivateData
->DevicePath
,
664 RegisteredPrivateData
->DevicePath
,
665 DevicePathSize
)) == 0) {
667 Status
= EFI_ALREADY_STARTED
;
675 // Fill Block IO protocol informations for the RAM disk
677 RamDiskInitBlockIo (PrivateData
);
680 // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL on a new
683 Status
= gBS
->InstallMultipleProtocolInterfaces (
684 &PrivateData
->Handle
,
685 &gEfiBlockIoProtocolGuid
,
686 &PrivateData
->BlockIo
,
687 &gEfiBlockIo2ProtocolGuid
,
688 &PrivateData
->BlockIo2
,
689 &gEfiDevicePathProtocolGuid
,
690 PrivateData
->DevicePath
,
693 if (EFI_ERROR (Status
)) {
698 // Insert the newly created one to the registered RAM disk list
700 InsertTailList (&RegisteredRamDisks
, &PrivateData
->ThisInstance
);
702 gBS
->ConnectController (PrivateData
->Handle
, NULL
, NULL
, TRUE
);
704 FreePool (RamDiskDevNode
);
706 if ((mAcpiTableProtocol
!= NULL
) && (mAcpiSdtProtocol
!= NULL
)) {
707 RamDiskPublishNfit (PrivateData
);
713 if (RamDiskDevNode
!= NULL
) {
714 FreePool (RamDiskDevNode
);
717 if (PrivateData
!= NULL
) {
718 if (PrivateData
->DevicePath
) {
719 FreePool (PrivateData
->DevicePath
);
722 FreePool (PrivateData
);
730 Unregister a RAM disk specified by DevicePath.
732 @param[in] DevicePath A pointer to the device path that describes a RAM
735 @retval EFI_SUCCESS The RAM disk is unregistered successfully.
736 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
737 @retval EFI_UNSUPPORTED The device specified by DevicePath is not a
738 valid ramdisk device path and not supported
740 @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
747 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
751 LIST_ENTRY
*NextEntry
;
755 EFI_DEVICE_PATH_PROTOCOL
*Header
;
756 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
757 RAM_DISK_PRIVATE_DATA
*PrivateData
;
759 if (NULL
== DevicePath
) {
760 return EFI_INVALID_PARAMETER
;
764 // Locate the RAM disk device node.
766 RamDiskDevNode
= NULL
;
770 // Test if the current device node is a RAM disk.
772 if ((MEDIA_DEVICE_PATH
== Header
->Type
) &&
773 (MEDIA_RAM_DISK_DP
== Header
->SubType
)) {
774 RamDiskDevNode
= (MEDIA_RAM_DISK_DEVICE_PATH
*) Header
;
779 Header
= NextDevicePathNode (Header
);
780 } while ((Header
->Type
!= END_DEVICE_PATH_TYPE
));
782 if (NULL
== RamDiskDevNode
) {
783 return EFI_UNSUPPORTED
;
787 StartingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->StartingAddr
[0]));
788 EndingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->EndingAddr
[0]));
790 if (!IsListEmpty(&RegisteredRamDisks
)) {
791 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
792 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
795 // Unregister the RAM disk given by its starting address, ending address
798 if ((StartingAddr
== PrivateData
->StartingAddr
) &&
799 (EndingAddr
== PrivateData
->StartingAddr
+ PrivateData
->Size
- 1) &&
800 (CompareGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
))) {
802 // Remove the content for this RAM disk in NFIT.
804 if (PrivateData
->InNfit
) {
805 RamDiskUnpublishNfit (PrivateData
);
809 // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL
811 gBS
->UninstallMultipleProtocolInterfaces (
813 &gEfiBlockIoProtocolGuid
,
814 &PrivateData
->BlockIo
,
815 &gEfiBlockIo2ProtocolGuid
,
816 &PrivateData
->BlockIo2
,
817 &gEfiDevicePathProtocolGuid
,
818 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
822 RemoveEntryList (&PrivateData
->ThisInstance
);
824 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
826 // If a RAM disk is created within HII, then the RamDiskDxe driver
827 // driver is responsible for freeing the allocated memory for the
830 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
833 FreePool (PrivateData
->DevicePath
);
834 FreePool (PrivateData
);
845 return EFI_NOT_FOUND
;