--- /dev/null
+/** @file\r
+ Linked List Library Functions.\r
+\r
+ Copyright (c) 2006, Intel Corporation<BR>\r
+ All rights reserved. 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: LinkedList.c\r
+\r
+**/\r
+\r
+#include "BaseLibInternals.h"\r
+\r
+/**\r
+ Worker function that locates the Node in the List\r
+\r
+ By searching the List, finds the location of the Node in List. At the same time,\r
+ verifies the validity of this list.\r
+\r
+ If List is NULL, then ASSERT().\r
+ If List->ForwardLink is NULL, then ASSERT().\r
+ If List->backLink is NULL, then ASSERT().\r
+ If Node is NULL, then ASSERT();\r
+ If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number\r
+ of nodes in ListHead, including the ListHead node, is greater than or\r
+ equal to PcdMaximumLinkedListLength, then ASSERT().\r
+\r
+ @param List A pointer to a node in a linked list.\r
+ @param Node A pointer to one nod.\r
+\r
+ @retval TRUE Node is in List\r
+ @retval FALSE Node isn't in List, or List is invalid\r
+\r
+**/\r
+BOOLEAN\r
+IsNodeInList (\r
+ IN CONST LIST_ENTRY *List,\r
+ IN CONST LIST_ENTRY *Node\r
+ )\r
+{\r
+ UINTN Count;\r
+ CONST LIST_ENTRY *Ptr;\r
+ BOOLEAN Found;\r
+\r
+ //\r
+ // Test the validity of List and Node\r
+ //\r
+ ASSERT (List != NULL);\r
+ ASSERT (List->ForwardLink != NULL);\r
+ ASSERT (List->BackLink != NULL);\r
+ ASSERT (Node != NULL);\r
+\r
+ Count = PcdGet32 (PcdMaximumLinkedListLength);\r
+\r
+ Ptr = List;\r
+ do {\r
+ Ptr = Ptr->ForwardLink;\r
+ Count--;\r
+ } while ((Ptr != List) && (Ptr != Node) && (Count > 0));\r
+ Found = (BOOLEAN)(Ptr == Node);\r
+\r
+ if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {\r
+ while ((Count > 0) && (Ptr != List)) {\r
+ Ptr = Ptr->ForwardLink;\r
+ Count--;\r
+ }\r
+ ASSERT (Count > 0);\r
+ }\r
+\r
+ return Found;\r
+}\r
+\r
+/**\r
+ Initializes the head node of a doubly linked list, and returns the pointer to\r
+ the head node of the doubly linked list.\r
+\r
+ Initializes the forward and backward links of a new linked list. After\r
+ initializing a linked list with this function, the other linked list\r
+ functions may be used to add and remove nodes from the linked list. It is up\r
+ to the caller of this function to allocate the memory for ListHead.\r
+\r
+ If ListHead is NULL, then ASSERT().\r
+\r
+ @param ListHead A pointer to the head node of a new doubly linked list.\r
+\r
+ @return ListHead\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+InitializeListHead (\r
+ IN OUT LIST_ENTRY *List\r
+ )\r
+\r
+{\r
+ ASSERT (List != NULL);\r
+\r
+ List->ForwardLink = List;\r
+ List->BackLink = List;\r
+ return List;\r
+}\r
+\r
+/**\r
+ Adds a node to the beginning of a doubly linked list, and returns the pointer\r
+ to the head node of the doubly linked list.\r
+\r
+ Adds the node Entry at the beginning of the doubly linked list denoted by\r
+ ListHead, and returns ListHead.\r
+\r
+ If ListHead is NULL, then ASSERT().\r
+ If Entry is NULL, then ASSERT().\r
+ If ListHead was not initialized with InitializeListHead(), then ASSERT().\r
+ If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number\r
+ of nodes in ListHead, including the ListHead node, is greater than or\r
+ equal to PcdMaximumLinkedListLength, then ASSERT().\r
+\r
+ @param ListHead A pointer to the head node of a doubly linked list.\r
+ @param Entry A pointer to a node that is to be inserted at the beginning\r
+ of a doubly linked list.\r
+\r
+ @return ListHead\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+InsertHeadList (\r
+ IN OUT LIST_ENTRY *List,\r
+ IN OUT LIST_ENTRY *Entry\r
+ )\r
+{\r
+ //\r
+ // ASSERT List not too long and Entry is not one of the nodes of List\r
+ //\r
+ ASSERT (!IsNodeInList (List, Entry));\r
+\r
+ Entry->ForwardLink = List->ForwardLink;\r
+ Entry->BackLink = List;\r
+ Entry->ForwardLink->BackLink = Entry;\r
+ List->ForwardLink = Entry;\r
+ return List;\r
+}\r
+\r
+/**\r
+ Adds a node to the end of a doubly linked list, and returns the pointer to\r
+ the head node of the doubly linked list.\r
+\r
+ Adds the node Entry to the end of the doubly linked list denoted by ListHead,\r
+ and returns ListHead.\r
+\r
+ If ListHead is NULL, then ASSERT().\r
+ If Entry is NULL, then ASSERT().\r
+ If ListHead was not initialized with InitializeListHead(), then ASSERT().\r
+ If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number\r
+ of nodes in ListHead, including the ListHead node, is greater than or\r
+ equal to PcdMaximumLinkedListLength, then ASSERT().\r
+\r
+ @param ListHead A pointer to the head node of a doubly linked list.\r
+ @param Entry A pointer to a node that is to be added at the end of the\r
+ doubly linked list.\r
+\r
+ @return ListHead\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+InsertTailList (\r
+ IN OUT LIST_ENTRY *List,\r
+ IN OUT LIST_ENTRY *Entry\r
+ )\r
+{\r
+ //\r
+ // ASSERT List not too long and Entry is not one of the nodes of List\r
+ //\r
+ ASSERT (!IsNodeInList (List, Entry));\r
+\r
+ Entry->ForwardLink = List;\r
+ Entry->BackLink = List->BackLink;\r
+ Entry->BackLink->ForwardLink = Entry;\r
+ List->BackLink = Entry;\r
+ return List;\r
+}\r
+\r
+/**\r
+ Retrieves the first node of a doubly linked list.\r
+\r
+ Returns the first node of a doubly linked list. List must have been\r
+ initialized with InitializeListHead(). If List is empty, then NULL is\r
+ returned.\r
+\r
+ If List is NULL, then ASSERT().\r
+ If List was not initialized with InitializeListHead(), then ASSERT().\r
+ If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+ in List, including the List node, is greater than or equal to\r
+ PcdMaximumLinkedListLength, then ASSERT().\r
+\r
+ @param List A pointer to the head node of a doubly linked list.\r
+\r
+ @return The first node of a doubly linked list.\r
+ @retval NULL The list is empty.\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+GetFirstNode (\r
+ IN CONST LIST_ENTRY *List\r
+ )\r
+{\r
+ //\r
+ // ASSERT List not too long\r
+ //\r
+ ASSERT (IsNodeInList (List, List));\r
+\r
+ return List->ForwardLink;\r
+}\r
+\r
+/**\r
+ Retrieves the next node of a doubly linked list.\r
+\r
+ Returns the node of a doubly linked list that follows Node. List must have\r
+ been initialized with InitializeListHead(). If List is empty, then List is\r
+ returned.\r
+\r
+ If List is NULL, then ASSERT().\r
+ If Node is NULL, then ASSERT().\r
+ If List was not initialized with InitializeListHead(), then ASSERT().\r
+ If PcdMaximumLinkedListLenth is not zero, and List contains more than\r
+ PcdMaximumLinkedListLenth nodes, then ASSERT().\r
+ If Node is not a node in List, then ASSERT().\r
+\r
+ @param List A pointer to the head node of a doubly linked list.\r
+ @param Node A pointer to a node in the doubly linked list.\r
+\r
+ @return Pointer to the next node if one exists. Otherwise a null value which\r
+ is actually List is returned.\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+GetNextNode (\r
+ IN CONST LIST_ENTRY *List,\r
+ IN CONST LIST_ENTRY *Node\r
+ )\r
+{\r
+ //\r
+ // ASSERT List not too long and Node is one of the nodes of List\r
+ //\r
+ ASSERT (IsNodeInList (List, Node));\r
+\r
+ return Node->ForwardLink;\r
+}\r
+\r
+/**\r
+ Checks to see if a doubly linked list is empty or not.\r
+\r
+ Checks to see if the doubly linked list is empty. If the linked list contains\r
+ zero nodes, this function returns TRUE. Otherwise, it returns FALSE.\r
+\r
+ If ListHead is NULL, then ASSERT().\r
+ If ListHead was not initialized with InitializeListHead(), then ASSERT().\r
+ If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+ in List, including the List node, is greater than or equal to\r
+ PcdMaximumLinkedListLength, then ASSERT().\r
+\r
+ @param ListHead A pointer to the head node of a doubly linked list.\r
+\r
+ @retval TRUE The linked list is empty.\r
+ @retval FALSE The linked list is not empty.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsListEmpty (\r
+ IN CONST LIST_ENTRY *List\r
+ )\r
+{\r
+ //\r
+ // ASSERT List not too long\r
+ //\r
+ ASSERT (IsNodeInList (List, List));\r
+\r
+ return (BOOLEAN)(List->ForwardLink == List);\r
+}\r
+\r
+/**\r
+ Determines if a node in a doubly linked list is null.\r
+\r
+ Returns FALSE if Node is one of the nodes in the doubly linked list specified\r
+ by List. Otherwise, TRUE is returned. List must have been initialized with\r
+ InitializeListHead().\r
+\r
+ If List is NULL, then ASSERT().\r
+ If Node is NULL, then ASSERT().\r
+ If List was not initialized with InitializeListHead(), then ASSERT().\r
+ If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+ in List, including the List node, is greater than or equal to\r
+ PcdMaximumLinkedListLength, then ASSERT().\r
+ If Node is not a node in List and Node is not equal to List, then ASSERT().\r
+\r
+ @param List A pointer to the head node of a doubly linked list.\r
+ @param Node A pointer to a node in the doubly linked list.\r
+\r
+ @retval TRUE Node is one of the nodes in the doubly linked list.\r
+ @retval FALSE Node is not one of the nodes in the doubly linked list.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsNull (\r
+ IN CONST LIST_ENTRY *List,\r
+ IN CONST LIST_ENTRY *Node\r
+ )\r
+{\r
+ //\r
+ // ASSERT List not too long and Node is one of the nodes of List\r
+ //\r
+ ASSERT (IsNodeInList (List, Node));\r
+\r
+ return (BOOLEAN)(Node == List);\r
+}\r
+\r
+/**\r
+ Determines if a node the last node in a doubly linked list.\r
+\r
+ Returns TRUE if Node is the last node in the doubly linked list specified by\r
+ List. Otherwise, FALSE is returned. List must have been initialized with\r
+ InitializeListHead().\r
+\r
+ If List is NULL, then ASSERT().\r
+ If Node is NULL, then ASSERT().\r
+ If List was not initialized with InitializeListHead(), then ASSERT().\r
+ If PcdMaximumLinkedListLenth is not zero, and the number of nodes\r
+ in List, including the List node, is greater than or equal to\r
+ PcdMaximumLinkedListLength, then ASSERT().\r
+ If Node is not a node in List, then ASSERT().\r
+\r
+ @param List A pointer to the head node of a doubly linked list.\r
+ @param Node A pointer to a node in the doubly linked list.\r
+\r
+ @retval TRUE Node is the last node in the linked list.\r
+ @retval FALSE Node is not the last node in the linked list.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsNodeAtEnd (\r
+ IN CONST LIST_ENTRY *List,\r
+ IN CONST LIST_ENTRY *Node\r
+ )\r
+{\r
+ //\r
+ // ASSERT List not too long and Node is one of the nodes of List\r
+ //\r
+ ASSERT (IsNodeInList (List, Node));\r
+\r
+ return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node);\r
+}\r
+\r
+/**\r
+ Swaps the location of two nodes in a doubly linked list, and returns the\r
+ first node after the swap.\r
+\r
+ If FirstEntry is identical to SecondEntry, then SecondEntry is returned.\r
+ Otherwise, the location of the FirstEntry node is swapped with the location\r
+ of the SecondEntry node in a doubly linked list. SecondEntry must be in the\r
+ same double linked list as FirstEntry and that double linked list must have\r
+ been initialized with InitializeListHead(). SecondEntry is returned after the\r
+ nodes are swapped.\r
+\r
+ If FirstEntry is NULL, then ASSERT().\r
+ If SecondEntry is NULL, then ASSERT().\r
+ If SecondEntry and FirstEntry are not in the same linked list, then ASSERT().\r
+ If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
+ linked list containing the FirstEntry and SecondEntry nodes, including\r
+ the FirstEntry and SecondEntry nodes, is greater than or equal to\r
+ PcdMaximumLinkedListLength, then ASSERT().\r
+\r
+ @param FirstEntry A pointer to a node in a linked list.\r
+ @param SecondEntry A pointer to another node in the same linked list.\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+SwapListEntries (\r
+ IN OUT LIST_ENTRY *FirstEntry,\r
+ IN OUT LIST_ENTRY *SecondEntry\r
+ )\r
+{\r
+ LIST_ENTRY *Ptr;\r
+\r
+ if (FirstEntry == SecondEntry) {\r
+ return SecondEntry;\r
+ }\r
+\r
+ //\r
+ // ASSERT Entry1 and Entry2 are in the same linked list\r
+ //\r
+ ASSERT (IsNodeInList (FirstEntry, SecondEntry));\r
+\r
+ //\r
+ // Ptr is the node pointed to by FirstEntry->ForwardLink\r
+ //\r
+ Ptr = RemoveEntryList (FirstEntry);\r
+\r
+ //\r
+ // If FirstEntry immediately follows SecondEntry, FirstEntry willl be placed\r
+ // immediately in front of SecondEntry\r
+ //\r
+ if (Ptr->BackLink == SecondEntry) {\r
+ return InsertTailList (SecondEntry, FirstEntry);\r
+ }\r
+\r
+ //\r
+ // Ptr == SecondEntry means SecondEntry immediately follows FirstEntry,\r
+ // then there are no further steps necessary\r
+ //\r
+ if (Ptr == InsertHeadList (SecondEntry, FirstEntry)) {\r
+ return Ptr;\r
+ }\r
+\r
+ //\r
+ // Move SecondEntry to the front of Ptr\r
+ //\r
+ RemoveEntryList (SecondEntry);\r
+ InsertTailList (Ptr, SecondEntry);\r
+ return SecondEntry;\r
+}\r
+\r
+/**\r
+ Removes a node from a doubly linked list, and returns the node that follows\r
+ the removed node.\r
+\r
+ Removes the node Entry from a doubly linked list. It is up to the caller of\r
+ this function to release the memory used by this node if that is required. On\r
+ exit, the node following Entry in the doubly linked list is returned. If\r
+ Entry is the only node in the linked list, then the head node of the linked\r
+ list is returned.\r
+\r
+ If Entry is NULL, then ASSERT().\r
+ If Entry is the head node of an empty list, then ASSERT().\r
+ If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
+ linked list containing Entry, including the Entry node, is greater than\r
+ or equal to PcdMaximumLinkedListLength, then ASSERT().\r
+\r
+ @param Entry A pointer to a node in a linked list\r
+\r
+ @return Entry\r
+\r
+**/\r
+LIST_ENTRY *\r
+EFIAPI\r
+RemoveEntryList (\r
+ IN CONST LIST_ENTRY *Entry\r
+ )\r
+{\r
+ ASSERT (!IsListEmpty (Entry));\r
+\r
+ Entry->ForwardLink->BackLink = Entry->BackLink;\r
+ Entry->BackLink->ForwardLink = Entry->ForwardLink;\r
+ return Entry->ForwardLink;\r
+}\r