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
;
207 while (!EFI_ERROR (Status
)) {
208 Status
= mAcpiSdtProtocol
->GetAcpiTable (
210 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
214 if (!EFI_ERROR (Status
)) {
217 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
218 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
224 if (!EFI_ERROR (Status
)) {
226 // A NFIT is already in the ACPI table.
230 "RamDiskPublishNfit: A NFIT is already exist in the ACPI Table.\n"
233 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
;
234 NfitLen
= NfitHeader
->Length
+ sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
235 Nfit
= AllocateZeroPool (NfitLen
);
237 return EFI_OUT_OF_RESOURCES
;
239 CopyMem (Nfit
, TableHeader
, NfitHeader
->Length
);
242 // Update the NFIT head pointer.
244 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
247 // Uninstall the origin NFIT from the ACPI table.
249 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
253 ASSERT_EFI_ERROR (Status
);
255 if (EFI_ERROR (Status
)) {
261 // Append the System Physical Address (SPA) Range Structure at the end
262 // of the origin NFIT.
264 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
265 ((UINT8
*)Nfit
+ NfitHeader
->Length
);
268 // Update the length field of the NFIT
270 NfitHeader
->Length
= NfitLen
;
273 // The checksum will be updated after the new contents are appended.
275 NfitHeader
->Checksum
= 0;
278 // Assumption is made that if no NFIT is in the ACPI table, there is no
279 // NVDIMM root device in the \SB scope.
280 // Therefore, a NVDIMM root device will be reported via Secondary System
281 // Description Table (SSDT).
283 Status
= RamDiskPublishSsdt ();
284 if (EFI_ERROR (Status
)) {
289 // No NFIT is in the ACPI table, we will create one here.
293 "RamDiskPublishNfit: No NFIT is in the ACPI Table, will create one.\n"
296 NfitLen
= sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
) +
297 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
298 Nfit
= AllocateZeroPool (NfitLen
);
300 return EFI_OUT_OF_RESOURCES
;
303 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)
304 ((UINT8
*)Nfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
306 NfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)Nfit
;
307 NfitHeader
->Signature
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
;
308 NfitHeader
->Length
= NfitLen
;
309 NfitHeader
->Revision
= EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION
;
310 NfitHeader
->Checksum
= 0;
311 NfitHeader
->OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
312 NfitHeader
->CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
313 NfitHeader
->CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
314 CurrentData
= PcdGet64 (PcdAcpiDefaultOemTableId
);
315 CopyMem (NfitHeader
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (NfitHeader
->OemId
));
316 CopyMem (&NfitHeader
->OemTableId
, &CurrentData
, sizeof (UINT64
));
320 // Fill in the content of the SPA Range Structure.
322 SpaRange
->Type
= EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
;
323 SpaRange
->Length
= sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
324 SpaRange
->SystemPhysicalAddressRangeBase
= PrivateData
->StartingAddr
;
325 SpaRange
->SystemPhysicalAddressRangeLength
= PrivateData
->Size
;
326 CopyGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
);
328 Checksum
= CalculateCheckSum8((UINT8
*)Nfit
, NfitHeader
->Length
);
329 NfitHeader
->Checksum
= Checksum
;
332 // Publish the NFIT to the ACPI table.
333 // Note, since the NFIT might be modified by other driver, therefore, we
334 // do not track the returning TableKey from the InstallAcpiTable().
336 Status
= mAcpiTableProtocol
->InstallAcpiTable (
342 ASSERT_EFI_ERROR (Status
);
346 if (EFI_ERROR (Status
)) {
350 PrivateData
->InNfit
= TRUE
;
357 Unpublish the RAM disk NVDIMM Firmware Interface Table (NFIT) from the
360 @param[in] PrivateData Points to RAM disk private data.
362 @retval EFI_SUCCESS The RAM disk NFIT has been unpublished.
363 @retval others The RAM disk NFIT has not been unpublished.
367 RamDiskUnpublishNfit (
368 IN RAM_DISK_PRIVATE_DATA
*PrivateData
374 EFI_ACPI_TABLE_VERSION TableVersion
;
376 EFI_ACPI_DESCRIPTION_HEADER
*NewNfitHeader
;
377 EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
381 EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*NfitStructHeader
;
387 // Find the NFIT in the ACPI table.
389 Status
= EFI_SUCCESS
;
392 while (!EFI_ERROR (Status
)) {
393 Status
= mAcpiSdtProtocol
->GetAcpiTable (
395 (EFI_ACPI_SDT_HEADER
**)&TableHeader
,
399 if (!EFI_ERROR (Status
)) {
402 if (((EFI_ACPI_SDT_HEADER
*)TableHeader
)->Signature
==
403 EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE
) {
409 if (EFI_ERROR (Status
)) {
411 // No NFIT is found in the ACPI table.
413 return EFI_NOT_FOUND
;
416 NewNfitLen
= ((EFI_ACPI_DESCRIPTION_HEADER
*)TableHeader
)->Length
-
417 sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
);
420 // After removing this RAM disk from the NFIT, if no other structure is in
421 // the NFIT, we just remove the NFIT and the SSDT which is used to report
422 // the NVDIMM root device.
424 if (NewNfitLen
== sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
)) {
428 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
432 ASSERT_EFI_ERROR (Status
);
433 if (EFI_ERROR (Status
)) {
438 // Remove the SSDT which is used by RamDiskDxe driver to report the NVDIMM
440 // We do not care the return status since this SSDT might already be
441 // uninstalled by other drivers to update the information of the NVDIMM
444 if (mRamDiskSsdtTableKeyValid
) {
445 mRamDiskSsdtTableKeyValid
= FALSE
;
447 mAcpiTableProtocol
->UninstallAcpiTable (
456 NewNfit
= AllocateZeroPool (NewNfitLen
);
457 if (NewNfit
== NULL
) {
458 return EFI_OUT_OF_RESOURCES
;
462 // Get a copy of the old NFIT header content.
464 CopyMem (NewNfit
, TableHeader
, sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
465 NewNfitHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)NewNfit
;
466 NewNfitHeader
->Length
= NewNfitLen
;
467 NewNfitHeader
->Checksum
= 0;
470 // Copy the content of required NFIT structures.
472 NewNfitPtr
= (UINT8
*)NewNfit
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
473 RemainLen
= NewNfitLen
- sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
);
474 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
475 ((UINT8
*)TableHeader
+ sizeof (EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE
));
476 while (RemainLen
> 0) {
477 if ((NfitStructHeader
->Type
== EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE
) &&
478 (NfitStructHeader
->Length
== sizeof (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
))) {
479 SpaRange
= (EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE
*)NfitStructHeader
;
481 if ((SpaRange
->SystemPhysicalAddressRangeBase
== PrivateData
->StartingAddr
) &&
482 (SpaRange
->SystemPhysicalAddressRangeLength
== PrivateData
->Size
) &&
483 (CompareGuid (&SpaRange
->AddressRangeTypeGUID
, &PrivateData
->TypeGuid
))) {
485 // Skip the SPA Range Structure for the RAM disk to be unpublished
488 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
489 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
495 // Copy the content of origin NFIT.
497 CopyMem (NewNfitPtr
, NfitStructHeader
, NfitStructHeader
->Length
);
498 NewNfitPtr
= (UINT8
*)NewNfitPtr
+ NfitStructHeader
->Length
;
501 // Move to the header of next NFIT structure.
503 RemainLen
-= NfitStructHeader
->Length
;
504 NfitStructHeader
= (EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER
*)
505 ((UINT8
*)NfitStructHeader
+ NfitStructHeader
->Length
);
508 Checksum
= CalculateCheckSum8((UINT8
*)NewNfit
, NewNfitHeader
->Length
);
509 NewNfitHeader
->Checksum
= Checksum
;
511 Status
= mAcpiTableProtocol
->UninstallAcpiTable (
515 ASSERT_EFI_ERROR (Status
);
517 if (EFI_ERROR (Status
)) {
523 // Publish the NFIT to the ACPI table.
524 // Note, since the NFIT might be modified by other driver, therefore, we
525 // do not track the returning TableKey from the InstallAcpiTable().
527 Status
= mAcpiTableProtocol
->InstallAcpiTable (
533 ASSERT_EFI_ERROR (Status
);
536 if (EFI_ERROR (Status
)) {
545 Register a RAM disk with specified address, size and type.
547 @param[in] RamDiskBase The base address of registered RAM disk.
548 @param[in] RamDiskSize The size of registered RAM disk.
549 @param[in] RamDiskType The type of registered RAM disk. The GUID can be
550 any of the values defined in section 9.3.6.9, or a
552 @param[in] ParentDevicePath
553 Pointer to the parent device path. If there is no
554 parent device path then ParentDevicePath is NULL.
555 @param[out] DevicePath On return, points to a pointer to the device path
556 of the RAM disk device.
557 If ParentDevicePath is not NULL, the returned
558 DevicePath is created by appending a RAM disk node
559 to the parent device path. If ParentDevicePath is
560 NULL, the returned DevicePath is a RAM disk device
561 path without appending. This function is
562 responsible for allocating the buffer DevicePath
563 with the boot service AllocatePool().
565 @retval EFI_SUCCESS The RAM disk is registered successfully.
566 @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
568 @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
569 is already present in the handle database.
570 @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
577 IN UINT64 RamDiskBase
,
578 IN UINT64 RamDiskSize
,
579 IN EFI_GUID
*RamDiskType
,
580 IN EFI_DEVICE_PATH
*ParentDevicePath OPTIONAL
,
581 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
585 RAM_DISK_PRIVATE_DATA
*PrivateData
;
586 RAM_DISK_PRIVATE_DATA
*RegisteredPrivateData
;
587 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
588 UINTN DevicePathSize
;
591 if ((0 == RamDiskSize
) || (NULL
== RamDiskType
) || (NULL
== DevicePath
)) {
592 return EFI_INVALID_PARAMETER
;
596 // Add check to prevent data read across the memory boundary
598 if (RamDiskBase
+ RamDiskSize
> ((UINTN
) -1) - RAM_DISK_BLOCK_SIZE
+ 1) {
599 return EFI_INVALID_PARAMETER
;
602 RamDiskDevNode
= NULL
;
605 // Create a new RAM disk instance and initialize its private data
607 PrivateData
= AllocateCopyPool (
608 sizeof (RAM_DISK_PRIVATE_DATA
),
609 &mRamDiskPrivateDataTemplate
611 if (NULL
== PrivateData
) {
612 return EFI_OUT_OF_RESOURCES
;
615 PrivateData
->StartingAddr
= RamDiskBase
;
616 PrivateData
->Size
= RamDiskSize
;
617 CopyGuid (&PrivateData
->TypeGuid
, RamDiskType
);
618 InitializeListHead (&PrivateData
->ThisInstance
);
621 // Generate device path information for the registered RAM disk
623 RamDiskDevNode
= AllocateCopyPool (
624 sizeof (MEDIA_RAM_DISK_DEVICE_PATH
),
625 &mRamDiskDeviceNodeTemplate
627 if (NULL
== RamDiskDevNode
) {
628 Status
= EFI_OUT_OF_RESOURCES
;
632 RamDiskInitDeviceNode (PrivateData
, RamDiskDevNode
);
634 *DevicePath
= AppendDevicePathNode (
636 (EFI_DEVICE_PATH_PROTOCOL
*) RamDiskDevNode
638 if (NULL
== *DevicePath
) {
639 Status
= EFI_OUT_OF_RESOURCES
;
643 PrivateData
->DevicePath
= *DevicePath
;
646 // Check whether the created device path is already present in the handle
649 if (!IsListEmpty(&RegisteredRamDisks
)) {
650 DevicePathSize
= GetDevicePathSize (PrivateData
->DevicePath
);
652 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
653 RegisteredPrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
654 if (DevicePathSize
== GetDevicePathSize (RegisteredPrivateData
->DevicePath
)) {
656 // Compare device path
659 PrivateData
->DevicePath
,
660 RegisteredPrivateData
->DevicePath
,
661 DevicePathSize
)) == 0) {
663 Status
= EFI_ALREADY_STARTED
;
671 // Fill Block IO protocol informations for the RAM disk
673 RamDiskInitBlockIo (PrivateData
);
676 // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL on a new
679 Status
= gBS
->InstallMultipleProtocolInterfaces (
680 &PrivateData
->Handle
,
681 &gEfiBlockIoProtocolGuid
,
682 &PrivateData
->BlockIo
,
683 &gEfiBlockIo2ProtocolGuid
,
684 &PrivateData
->BlockIo2
,
685 &gEfiDevicePathProtocolGuid
,
686 PrivateData
->DevicePath
,
689 if (EFI_ERROR (Status
)) {
694 // Insert the newly created one to the registered RAM disk list
696 InsertTailList (&RegisteredRamDisks
, &PrivateData
->ThisInstance
);
699 gBS
->ConnectController (PrivateData
->Handle
, NULL
, NULL
, TRUE
);
701 FreePool (RamDiskDevNode
);
703 if ((mAcpiTableProtocol
!= NULL
) && (mAcpiSdtProtocol
!= NULL
)) {
704 RamDiskPublishNfit (PrivateData
);
710 if (RamDiskDevNode
!= NULL
) {
711 FreePool (RamDiskDevNode
);
714 if (PrivateData
!= NULL
) {
715 if (PrivateData
->DevicePath
) {
716 FreePool (PrivateData
->DevicePath
);
719 FreePool (PrivateData
);
727 Unregister a RAM disk specified by DevicePath.
729 @param[in] DevicePath A pointer to the device path that describes a RAM
732 @retval EFI_SUCCESS The RAM disk is unregistered successfully.
733 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
734 @retval EFI_UNSUPPORTED The device specified by DevicePath is not a
735 valid ramdisk device path and not supported
737 @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
744 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
748 LIST_ENTRY
*NextEntry
;
752 EFI_DEVICE_PATH_PROTOCOL
*Header
;
753 MEDIA_RAM_DISK_DEVICE_PATH
*RamDiskDevNode
;
754 RAM_DISK_PRIVATE_DATA
*PrivateData
;
756 if (NULL
== DevicePath
) {
757 return EFI_INVALID_PARAMETER
;
761 // Locate the RAM disk device node.
763 RamDiskDevNode
= NULL
;
767 // Test if the current device node is a RAM disk.
769 if ((MEDIA_DEVICE_PATH
== Header
->Type
) &&
770 (MEDIA_RAM_DISK_DP
== Header
->SubType
)) {
771 RamDiskDevNode
= (MEDIA_RAM_DISK_DEVICE_PATH
*) Header
;
776 Header
= NextDevicePathNode (Header
);
777 } while ((Header
->Type
!= END_DEVICE_PATH_TYPE
));
779 if (NULL
== RamDiskDevNode
) {
780 return EFI_UNSUPPORTED
;
784 StartingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->StartingAddr
[0]));
785 EndingAddr
= ReadUnaligned64 ((UINT64
*) &(RamDiskDevNode
->EndingAddr
[0]));
787 if (!IsListEmpty(&RegisteredRamDisks
)) {
788 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
789 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
792 // Unregister the RAM disk given by its starting address, ending address
795 if ((StartingAddr
== PrivateData
->StartingAddr
) &&
796 (EndingAddr
== PrivateData
->StartingAddr
+ PrivateData
->Size
- 1) &&
797 (CompareGuid (&RamDiskDevNode
->TypeGuid
, &PrivateData
->TypeGuid
))) {
799 // Remove the content for this RAM disk in NFIT.
801 if (PrivateData
->InNfit
) {
802 RamDiskUnpublishNfit (PrivateData
);
806 // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO(2)_PROTOCOL
808 gBS
->UninstallMultipleProtocolInterfaces (
810 &gEfiBlockIoProtocolGuid
,
811 &PrivateData
->BlockIo
,
812 &gEfiBlockIo2ProtocolGuid
,
813 &PrivateData
->BlockIo2
,
814 &gEfiDevicePathProtocolGuid
,
815 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
819 RemoveEntryList (&PrivateData
->ThisInstance
);
821 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
823 // If a RAM disk is created within HII, then the RamDiskDxe driver
824 // driver is responsible for freeing the allocated memory for the
827 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
830 FreePool (PrivateData
->DevicePath
);
831 FreePool (PrivateData
);
843 return EFI_NOT_FOUND
;