+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- DevicePath.c\r
-\r
-Abstract:\r
-\r
- Device Path services. The thing to remember is device paths are built out of\r
- nodes. The device path is terminated by an end node that is length\r
- sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)\r
- all over this file.\r
-\r
- The only place where multi-instance device paths are supported is in\r
- environment varibles. Multi-instance device paths should never be placed\r
- on a Handle.\r
-\r
---*/\r
-\r
-#include "Tiano.h"\r
-#include "EfiDriverLib.h"\r
-#include EFI_PROTOCOL_DEFINITION (DevicePath)\r
-\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EfiDevicePathInstance (\r
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
- OUT UINTN *Size\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Function retrieves the next device path instance from a device path data structure.\r
-\r
-Arguments:\r
- DevicePath - A pointer to a device path data structure.\r
-\r
- Size - A pointer to the size of a device path instance in bytes.\r
-\r
-Returns:\r
-\r
- This function returns a pointer to the current device path instance.\r
- In addition, it returns the size in bytes of the current device path instance in Size,\r
- and a pointer to the next device path instance in DevicePath.\r
- If there are no more device path instances in DevicePath, then DevicePath will be set to NULL.\r
-\r
---*/\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
- EFI_DEVICE_PATH_PROTOCOL *ReturnValue;\r
- UINT8 Temp;\r
-\r
- if (*DevicePath == NULL) {\r
- if (Size != NULL) {\r
- *Size = 0;\r
- }\r
-\r
- return NULL;\r
- }\r
-\r
- //\r
- // Find the end of the device path instance\r
- //\r
- DevPath = *DevicePath;\r
- while (!IsDevicePathEndType (DevPath)) {\r
- DevPath = NextDevicePathNode (DevPath);\r
- }\r
-\r
- //\r
- // Compute the size of the device path instance\r
- //\r
- if (Size != NULL) {\r
- *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
- }\r
-\r
- //\r
- // Make a copy and return the device path instance\r
- //\r
- Temp = DevPath->SubType;\r
- DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
- ReturnValue = EfiDuplicateDevicePath (*DevicePath);\r
- DevPath->SubType = Temp;\r
-\r
- //\r
- // If DevPath is the end of an entire device path, then another instance\r
- // does not follow, so *DevicePath is set to NULL.\r
- //\r
- if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) {\r
- *DevicePath = NULL;\r
- } else {\r
- *DevicePath = NextDevicePathNode (DevPath);\r
- }\r
-\r
- return ReturnValue;\r
-}\r
-\r
-BOOLEAN\r
-EfiIsDevicePathMultiInstance (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Return TRUE is this is a multi instance device path.\r
-\r
-Arguments:\r
- DevicePath - A pointer to a device path data structure.\r
-\r
-\r
-Returns:\r
- TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi\r
- instance.\r
-\r
---*/\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *Node;\r
-\r
- if (DevicePath == NULL) {\r
- return FALSE;\r
- }\r
-\r
- Node = DevicePath;\r
- while (!EfiIsDevicePathEnd (Node)) {\r
- if (EfiIsDevicePathEndInstance (Node)) {\r
- return TRUE;\r
- }\r
-\r
- Node = EfiNextDevicePathNode (Node);\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-UINTN\r
-EfiDevicePathSize (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Calculate the space size of a device path.\r
-\r
-Arguments:\r
-\r
- DevicePath - A specified device path\r
-\r
-Returns:\r
-\r
- The size.\r
-\r
---*/\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *Start;\r
-\r
- if (DevicePath == NULL) {\r
- return 0;\r
- }\r
-\r
- //\r
- // Search for the end of the device path structure\r
- //\r
- Start = DevicePath;\r
- while (!EfiIsDevicePathEnd (DevicePath)) {\r
- DevicePath = EfiNextDevicePathNode (DevicePath);\r
- }\r
-\r
- //\r
- // Compute the size and add back in the size of the end device path structure\r
- //\r
- return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
-}\r
-\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EfiDevicePathFromHandle (\r
- IN EFI_HANDLE Handle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get the device path protocol interface installed on a specified handle.\r
-\r
-Arguments:\r
-\r
- Handle - a specified handle\r
-\r
-Returns:\r
-\r
- The device path protocol interface installed on that handle.\r
-\r
---*/\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- DevicePath = NULL;\r
- gBS->HandleProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID *) &DevicePath\r
- );\r
- return DevicePath;\r
-}\r
-\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EfiDuplicateDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Duplicate a device path structure.\r
-\r
-Arguments:\r
-\r
- DevicePath - The device path to duplicated.\r
-\r
-Returns:\r
-\r
- The duplicated device path.\r
-\r
---*/\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
- UINTN Size;\r
-\r
- if (DevicePath == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Compute the size\r
- //\r
- Size = EfiDevicePathSize (DevicePath);\r
- if (Size == 0) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Allocate space for duplicate device path\r
- //\r
- NewDevicePath = EfiLibAllocateCopyPool (Size, DevicePath);\r
-\r
- return NewDevicePath;\r
-}\r
-\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EfiAppendDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *Src1,\r
- IN EFI_DEVICE_PATH_PROTOCOL *Src2\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Function is used to append a Src1 and Src2 together.\r
-\r
-Arguments:\r
- Src1 - A pointer to a device path data structure.\r
-\r
- Src2 - A pointer to a device path data structure.\r
-\r
-Returns:\r
-\r
- A pointer to the new device path is returned.\r
- NULL is returned if space for the new device path could not be allocated from pool.\r
- It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.\r
-\r
---*/\r
-{\r
- UINTN Size;\r
- UINTN Size1;\r
- UINTN Size2;\r
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath;\r
-\r
- //\r
- // If there's only 1 path, just duplicate it\r
- //\r
- if (!Src1) {\r
- ASSERT (!IsDevicePathUnpacked (Src2));\r
- return EfiDuplicateDevicePath (Src2);\r
- }\r
-\r
- if (!Src2) {\r
- ASSERT (!IsDevicePathUnpacked (Src1));\r
- return EfiDuplicateDevicePath (Src1);\r
- }\r
-\r
- //\r
- // Allocate space for the combined device path. It only has one end node of\r
- // length EFI_DEVICE_PATH_PROTOCOL\r
- //\r
- Size1 = EfiDevicePathSize (Src1);\r
- Size2 = EfiDevicePathSize (Src2);\r
- Size = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
-\r
- NewDevicePath = EfiLibAllocateCopyPool (Size, Src1);\r
-\r
- if (NewDevicePath != NULL) {\r
-\r
- //\r
- // Over write Src1 EndNode and do the copy\r
- //\r
- SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL)));\r
- EfiCopyMem (SecondDevicePath, Src2, Size2);\r
- }\r
-\r
- return NewDevicePath;\r
-}\r
-\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EfiAppendDevicePathNode (\r
- IN EFI_DEVICE_PATH_PROTOCOL *Src1,\r
- IN EFI_DEVICE_PATH_PROTOCOL *Node\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Function is used to append a device path node to the end of another device path.\r
-\r
-Arguments:\r
- Src1 - A pointer to a device path data structure.\r
-\r
- Node - A pointer to a device path data structure.\r
-\r
-Returns:\r
- This function returns a pointer to the new device path.\r
- If there is not enough temporary pool memory available to complete this function,\r
- then NULL is returned.\r
-\r
-\r
---*/\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *Temp;\r
- EFI_DEVICE_PATH_PROTOCOL *NextNode;\r
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
- UINTN NodeLength;\r
-\r
- //\r
- // Build a Node that has a terminator on it\r
- //\r
- NodeLength = DevicePathNodeLength (Node);\r
-\r
- Temp = EfiLibAllocateCopyPool (NodeLength + sizeof (EFI_DEVICE_PATH_PROTOCOL), Node);\r
- if (Temp == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Add and end device path node to convert Node to device path\r
- //\r
- NextNode = NextDevicePathNode (Temp);\r
- SetDevicePathEndNode (NextNode);\r
-\r
- //\r
- // Append device paths\r
- //\r
- NewDevicePath = EfiAppendDevicePath (Src1, Temp);\r
- gBS->FreePool (Temp);\r
- return NewDevicePath;\r
-}\r
-\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EfiFileDevicePath (\r
- IN EFI_HANDLE Device OPTIONAL,\r
- IN CHAR16 *FileName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This function allocates a device path for a file and appends it to an existiong\r
- device path.\r
-\r
-Arguments:\r
- Device - A pointer to a device handle.\r
-\r
- FileName - A pointer to a Null-terminated Unicodestring.\r
-\r
-Returns:\r
- A device path contain the file name.\r
-\r
---*/\r
-{\r
- UINTN Size;\r
- FILEPATH_DEVICE_PATH *FilePath;\r
- EFI_DEVICE_PATH_PROTOCOL *Eop;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- for (Size = 0; FileName[Size] != 0; Size++)\r
- ;\r
- Size = (Size + 1) * 2;\r
-\r
- FilePath = EfiLibAllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
-\r
- DevicePath = NULL;\r
-\r
- if (FilePath != NULL) {\r
-\r
- //\r
- // Build a file path\r
- //\r
- FilePath->Header.Type = MEDIA_DEVICE_PATH;\r
- FilePath->Header.SubType = MEDIA_FILEPATH_DP;\r
- SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);\r
- EfiCopyMem (FilePath->PathName, FileName, Size);\r
- Eop = NextDevicePathNode (&FilePath->Header);\r
- SetDevicePathEndNode (Eop);\r
-\r
- //\r
- // Append file path to device's device path\r
- //\r
-\r
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;\r
- if (Device != NULL) {\r
- DevicePath = EfiAppendDevicePath (\r
- EfiDevicePathFromHandle (Device),\r
- DevicePath\r
- );\r
-\r
- gBS->FreePool (FilePath);\r
- }\r
- }\r
-\r
- return DevicePath;\r
-}\r
-\r
-EFI_DEVICE_PATH_PROTOCOL *\r
-EfiAppendDevicePathInstance (\r
- IN EFI_DEVICE_PATH_PROTOCOL *Src,\r
- IN EFI_DEVICE_PATH_PROTOCOL *Instance\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Append a device path instance to another.\r
-\r
-Arguments:\r
-\r
- Src - The device path instance to be appended with.\r
- Instance - The device path instance appending the other.\r
-\r
-Returns:\r
-\r
- The contaction of these two.\r
-\r
---*/\r
-{\r
- UINT8 *Ptr;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
- UINTN SrcSize;\r
- UINTN InstanceSize;\r
-\r
- if (Src == NULL) {\r
- return EfiDuplicateDevicePath (Instance);\r
- }\r
-\r
- SrcSize = EfiDevicePathSize (Src);\r
- InstanceSize = EfiDevicePathSize (Instance);\r
-\r
- Ptr = EfiLibAllocateCopyPool (SrcSize + InstanceSize, Src);\r
- if (Ptr != NULL) {\r
-\r
- DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
-\r
- while (!IsDevicePathEnd (DevPath)) {\r
- DevPath = NextDevicePathNode (DevPath);\r
- }\r
- //\r
- // Convert the End to an End Instance, since we are\r
- // appending another instacne after this one its a good\r
- // idea.\r
- //\r
- DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;\r
-\r
- DevPath = NextDevicePathNode (DevPath);\r
- EfiCopyMem (DevPath, Instance, InstanceSize);\r
- }\r
-\r
- return (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
-}\r
-\r
-VOID\r
-EFIAPI\r
-EfiInitializeFwVolDevicepathNode (\r
- IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode,\r
- IN EFI_GUID *NameGuid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Initialize a Firmware Volume (FV) Media Device Path node.\r
- \r
-Arguments:\r
-\r
- FvDevicePathNode - Pointer to a FV device path node to initialize\r
- NameGuid - FV file name to use in FvDevicePathNode\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- FvDevicePathNode->Header.Type = MEDIA_DEVICE_PATH;\r
- FvDevicePathNode->Header.SubType = MEDIA_FV_FILEPATH_DP;\r
- SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));\r
-\r
- EfiCopyMem (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));\r
-}\r
-\r
-EFI_GUID *\r
-EFIAPI\r
-EfiGetNameGuidFromFwVolDevicePathNode (\r
- IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check to see if the Firmware Volume (FV) Media Device Path is valid.\r
- \r
-Arguments:\r
-\r
- FvDevicePathNode - Pointer to FV device path to check\r
-\r
-Returns:\r
-\r
- NULL - FvDevicePathNode is not valid.\r
- Other - FvDevicePathNode is valid and pointer to NameGuid was returned.\r
-\r
---*/\r
-{\r
- if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&\r
- DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {\r
- return &FvDevicePathNode->NameGuid;\r
- }\r
-\r
- return NULL;\r
-}\r