mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 13:02:07 +00:00 
			
		
		
		
	 d9da5f5982
			
		
	
	
		d9da5f5982
		
	
	
	
	
		
			
			2. Fix one bug in Ipf/InterlockedCompareExchange64.s 3. Fix one bug in AsmDisablePaging64() git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@786 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			444 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			444 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Linked List Library Functions.
 | |
| 
 | |
|   Copyright (c) 2006, Intel Corporation<BR>
 | |
|   All rights reserved. This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
|   Module Name:  LinkedList.c
 | |
| 
 | |
| **/
 | |
| 
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| IsNodeInList (
 | |
|   IN      CONST LIST_ENTRY      *List,
 | |
|   IN      CONST LIST_ENTRY      *Node
 | |
|   )
 | |
| {
 | |
|   UINTN                         Count;
 | |
|   CONST LIST_ENTRY              *Ptr;
 | |
|   BOOLEAN                       Found;
 | |
| 
 | |
|   //
 | |
|   // Test the validity of List and Node
 | |
|   //
 | |
|   ASSERT (List != NULL);
 | |
|   ASSERT (List->ForwardLink != NULL);
 | |
|   ASSERT (List->BackLink != NULL);
 | |
|   ASSERT (Node != NULL);
 | |
| 
 | |
|   Count = PcdGet32 (PcdMaximumLinkedListLength);
 | |
| 
 | |
|   Ptr = List;
 | |
|   do {
 | |
|     Ptr = Ptr->ForwardLink;
 | |
|     Count--;
 | |
|   } while ((Ptr != List) && (Ptr != Node) && (Count > 0));
 | |
|   Found = (BOOLEAN)(Ptr == Node);
 | |
| 
 | |
|   if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {
 | |
|     while ((Count > 0) && (Ptr != List)) {
 | |
|       Ptr = Ptr->ForwardLink;
 | |
|       Count--;
 | |
|     }
 | |
|     ASSERT (Count > 0);
 | |
|   }
 | |
| 
 | |
|   return Found;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initializes the head node of a doubly linked list, and returns the pointer to
 | |
|   the head node of the doubly linked list.
 | |
| 
 | |
|   Initializes the forward and backward links of a new linked list. After
 | |
|   initializing a linked list with this function, the other linked list
 | |
|   functions may be used to add and remove nodes from the linked list. It is up
 | |
|   to the caller of this function to allocate the memory for ListHead.
 | |
| 
 | |
|   If ListHead is NULL, then ASSERT().
 | |
| 
 | |
|   @param  ListHead  A pointer to the head node of a new doubly linked list.
 | |
| 
 | |
|   @return ListHead
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| EFIAPI
 | |
| InitializeListHead (
 | |
|   IN OUT  LIST_ENTRY            *List
 | |
|   )
 | |
| 
 | |
| {
 | |
|   ASSERT (List != NULL);
 | |
| 
 | |
|   List->ForwardLink = List;
 | |
|   List->BackLink = List;
 | |
|   return List;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adds a node to the beginning of a doubly linked list, and returns the pointer
 | |
|   to the head node of the doubly linked list.
 | |
| 
 | |
|   Adds the node Entry at the beginning of the doubly linked list denoted by
 | |
|   ListHead, and returns ListHead.
 | |
| 
 | |
|   If ListHead is NULL, then ASSERT().
 | |
|   If Entry is NULL, then ASSERT().
 | |
|   If ListHead was not initialized with InitializeListHead(), then ASSERT().
 | |
|   If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number
 | |
|   of nodes in ListHead, including the ListHead node, is greater than or 
 | |
|   equal to PcdMaximumLinkedListLength, then ASSERT().
 | |
| 
 | |
|   @param  ListHead  A pointer to the head node of a doubly linked list.
 | |
|   @param  Entry     A pointer to a node that is to be inserted at the beginning
 | |
|                     of a doubly linked list.
 | |
| 
 | |
|   @return ListHead
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| EFIAPI
 | |
| InsertHeadList (
 | |
|   IN OUT  LIST_ENTRY            *List,
 | |
|   IN OUT  LIST_ENTRY            *Entry
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // ASSERT List not too long and Entry is not one of the nodes of List
 | |
|   //
 | |
|   ASSERT (!IsNodeInList (List, Entry));
 | |
| 
 | |
|   Entry->ForwardLink = List->ForwardLink;
 | |
|   Entry->BackLink = List;
 | |
|   Entry->ForwardLink->BackLink = Entry;
 | |
|   List->ForwardLink = Entry;
 | |
|   return List;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adds a node to the end of a doubly linked list, and returns the pointer to
 | |
|   the head node of the doubly linked list.
 | |
| 
 | |
|   Adds the node Entry to the end of the doubly linked list denoted by ListHead,
 | |
|   and returns ListHead.
 | |
| 
 | |
|   If ListHead is NULL, then ASSERT().
 | |
|   If Entry is NULL, then ASSERT().
 | |
|   If ListHead was not initialized with InitializeListHead(), then ASSERT().
 | |
|   If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number
 | |
|   of nodes in ListHead, including the ListHead node, is greater than or 
 | |
|   equal to PcdMaximumLinkedListLength, then ASSERT().
 | |
| 
 | |
|   @param  ListHead  A pointer to the head node of a doubly linked list.
 | |
|   @param  Entry     A pointer to a node that is to be added at the end of the
 | |
|                     doubly linked list.
 | |
| 
 | |
|   @return ListHead
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| EFIAPI
 | |
| InsertTailList (
 | |
|   IN OUT  LIST_ENTRY            *List,
 | |
|   IN OUT  LIST_ENTRY            *Entry
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // ASSERT List not too long and Entry is not one of the nodes of List
 | |
|   //
 | |
|   ASSERT (!IsNodeInList (List, Entry));
 | |
| 
 | |
|   Entry->ForwardLink = List;
 | |
|   Entry->BackLink = List->BackLink;
 | |
|   Entry->BackLink->ForwardLink = Entry;
 | |
|   List->BackLink = Entry;
 | |
|   return List;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieves the first node of a doubly linked list.
 | |
| 
 | |
|   Returns the first node of a doubly linked list. List must have been
 | |
|   initialized with InitializeListHead(). If List is empty, then NULL is
 | |
|   returned.
 | |
| 
 | |
|   If List is NULL, then ASSERT().
 | |
|   If List was not initialized with InitializeListHead(), then ASSERT().
 | |
|   If PcdMaximumLinkedListLenth is not zero, and the number of nodes 
 | |
|   in List, including the List node, is greater than or equal to 
 | |
|   PcdMaximumLinkedListLength, then ASSERT().
 | |
| 
 | |
|   @param  List  A pointer to the head node of a doubly linked list.
 | |
| 
 | |
|   @return The first node of a doubly linked list.
 | |
|   @retval NULL  The list is empty.
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| EFIAPI
 | |
| GetFirstNode (
 | |
|   IN CONST LIST_ENTRY  *List
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // ASSERT List not too long
 | |
|   //
 | |
|   ASSERT (IsNodeInList (List, List));
 | |
| 
 | |
|   return List->ForwardLink;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieves the next node of a doubly linked list.
 | |
| 
 | |
|   Returns the node of a doubly linked list that follows Node. List must have
 | |
|   been initialized with InitializeListHead(). If List is empty, then List is
 | |
|   returned.
 | |
| 
 | |
|   If List is NULL, then ASSERT().
 | |
|   If Node is NULL, then ASSERT().
 | |
|   If List was not initialized with InitializeListHead(), then ASSERT().
 | |
|   If PcdMaximumLinkedListLenth is not zero, and List contains more than
 | |
|   PcdMaximumLinkedListLenth nodes, then ASSERT().
 | |
|   If Node is not a node in List, then ASSERT().
 | |
| 
 | |
|   @param  List  A pointer to the head node of a doubly linked list.
 | |
|   @param  Node  A pointer to a node in the doubly linked list.
 | |
| 
 | |
|   @return Pointer to the next node if one exists. Otherwise a null value which
 | |
|           is actually List is returned.
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| EFIAPI
 | |
| GetNextNode (
 | |
|   IN CONST LIST_ENTRY  *List,
 | |
|   IN CONST LIST_ENTRY  *Node
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // ASSERT List not too long and Node is one of the nodes of List
 | |
|   //
 | |
|   ASSERT (IsNodeInList (List, Node));
 | |
| 
 | |
|   return Node->ForwardLink;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Checks to see if a doubly linked list is empty or not.
 | |
| 
 | |
|   Checks to see if the doubly linked list is empty. If the linked list contains
 | |
|   zero nodes, this function returns TRUE. Otherwise, it returns FALSE.
 | |
| 
 | |
|   If ListHead is NULL, then ASSERT().
 | |
|   If ListHead was not initialized with InitializeListHead(), then ASSERT().
 | |
|   If PcdMaximumLinkedListLenth is not zero, and the number of nodes 
 | |
|   in List, including the List node, is greater than or equal to 
 | |
|   PcdMaximumLinkedListLength, then ASSERT().
 | |
| 
 | |
|   @param  ListHead  A pointer to the head node of a doubly linked list.
 | |
| 
 | |
|   @retval TRUE  The linked list is empty.
 | |
|   @retval FALSE The linked list is not empty.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| IsListEmpty (
 | |
|   IN      CONST LIST_ENTRY      *List
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // ASSERT List not too long
 | |
|   //
 | |
|   ASSERT (IsNodeInList (List, List));
 | |
| 
 | |
|   return (BOOLEAN)(List->ForwardLink == List);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Determines if a node in a doubly linked list is null.
 | |
| 
 | |
|   Returns FALSE if Node is one of the nodes in the doubly linked list specified
 | |
|   by List. Otherwise, TRUE is returned. List must have been initialized with
 | |
|   InitializeListHead().
 | |
| 
 | |
|   If List is NULL, then ASSERT().
 | |
|   If Node is NULL, then ASSERT().
 | |
|   If List was not initialized with InitializeListHead(), then ASSERT().
 | |
|   If PcdMaximumLinkedListLenth is not zero, and the number of nodes 
 | |
|   in List, including the List node, is greater than or equal to 
 | |
|   PcdMaximumLinkedListLength, then ASSERT().
 | |
|   If Node is not a node in List and Node is not equal to List, then ASSERT().
 | |
| 
 | |
|   @param  List  A pointer to the head node of a doubly linked list.
 | |
|   @param  Node  A pointer to a node in the doubly linked list.
 | |
| 
 | |
|   @retval TRUE  Node is one of the nodes in the doubly linked list.
 | |
|   @retval FALSE Node is not one of the nodes in the doubly linked list.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| IsNull (
 | |
|   IN      CONST LIST_ENTRY      *List,
 | |
|   IN      CONST LIST_ENTRY      *Node
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // ASSERT List not too long and Node is one of the nodes of List
 | |
|   //
 | |
|   ASSERT (IsNodeInList (List, Node));
 | |
| 
 | |
|   return (BOOLEAN)(Node == List);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Determines if a node the last node in a doubly linked list.
 | |
| 
 | |
|   Returns TRUE if Node is the last node in the doubly linked list specified by
 | |
|   List. Otherwise, FALSE is returned. List must have been initialized with
 | |
|   InitializeListHead().
 | |
| 
 | |
|   If List is NULL, then ASSERT().
 | |
|   If Node is NULL, then ASSERT().
 | |
|   If List was not initialized with InitializeListHead(), then ASSERT().
 | |
|   If PcdMaximumLinkedListLenth is not zero, and the number of nodes 
 | |
|   in List, including the List node, is greater than or equal to 
 | |
|   PcdMaximumLinkedListLength, then ASSERT().
 | |
|   If Node is not a node in List, then ASSERT().
 | |
| 
 | |
|   @param  List  A pointer to the head node of a doubly linked list.
 | |
|   @param  Node  A pointer to a node in the doubly linked list.
 | |
| 
 | |
|   @retval TRUE  Node is the last node in the linked list.
 | |
|   @retval FALSE Node is not the last node in the linked list.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| IsNodeAtEnd (
 | |
|   IN      CONST LIST_ENTRY      *List,
 | |
|   IN      CONST LIST_ENTRY      *Node
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // ASSERT List not too long and Node is one of the nodes of List
 | |
|   //
 | |
|   ASSERT (IsNodeInList (List, Node));
 | |
| 
 | |
|   return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Swaps the location of two nodes in a doubly linked list, and returns the
 | |
|   first node after the swap.
 | |
| 
 | |
|   If FirstEntry is identical to SecondEntry, then SecondEntry is returned.
 | |
|   Otherwise, the location of the FirstEntry node is swapped with the location
 | |
|   of the SecondEntry node in a doubly linked list. SecondEntry must be in the
 | |
|   same double linked list as FirstEntry and that double linked list must have
 | |
|   been initialized with InitializeListHead(). SecondEntry is returned after the
 | |
|   nodes are swapped.
 | |
| 
 | |
|   If FirstEntry is NULL, then ASSERT().
 | |
|   If SecondEntry is NULL, then ASSERT().
 | |
|   If SecondEntry and FirstEntry are not in the same linked list, then ASSERT().
 | |
|   If PcdMaximumLinkedListLength is not zero, and the number of nodes in the
 | |
|   linked list containing the FirstEntry and SecondEntry nodes, including
 | |
|   the FirstEntry and SecondEntry nodes, is greater than or equal to 
 | |
|   PcdMaximumLinkedListLength, then ASSERT().
 | |
| 
 | |
|   @param  FirstEntry  A pointer to a node in a linked list.
 | |
|   @param  SecondEntry A pointer to another node in the same linked list.
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| EFIAPI
 | |
| SwapListEntries (
 | |
|   IN OUT  LIST_ENTRY            *FirstEntry,
 | |
|   IN OUT  LIST_ENTRY            *SecondEntry
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY                    *Ptr;
 | |
| 
 | |
|   if (FirstEntry == SecondEntry) {
 | |
|     return SecondEntry;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // ASSERT Entry1 and Entry2 are in the same linked list
 | |
|   //
 | |
|   ASSERT (IsNodeInList (FirstEntry, SecondEntry));
 | |
| 
 | |
|   //
 | |
|   // Ptr is the node pointed to by FirstEntry->ForwardLink
 | |
|   //
 | |
|   Ptr = RemoveEntryList (FirstEntry);
 | |
| 
 | |
|   //
 | |
|   // If FirstEntry immediately follows SecondEntry, FirstEntry willl be placed
 | |
|   // immediately in front of SecondEntry
 | |
|   //
 | |
|   if (Ptr->BackLink == SecondEntry) {
 | |
|     return InsertTailList (SecondEntry, FirstEntry);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Ptr == SecondEntry means SecondEntry immediately follows FirstEntry,
 | |
|   // then there are no further steps necessary
 | |
|   //
 | |
|   if (Ptr == InsertHeadList (SecondEntry, FirstEntry)) {
 | |
|     return Ptr;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Move SecondEntry to the front of Ptr
 | |
|   //
 | |
|   RemoveEntryList (SecondEntry);
 | |
|   InsertTailList (Ptr, SecondEntry);
 | |
|   return SecondEntry;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Removes a node from a doubly linked list, and returns the node that follows
 | |
|   the removed node.
 | |
| 
 | |
|   Removes the node Entry from a doubly linked list. It is up to the caller of
 | |
|   this function to release the memory used by this node if that is required. On
 | |
|   exit, the node following Entry in the doubly linked list is returned. If
 | |
|   Entry is the only node in the linked list, then the head node of the linked
 | |
|   list is returned.
 | |
| 
 | |
|   If Entry is NULL, then ASSERT().
 | |
|   If Entry is the head node of an empty list, then ASSERT().
 | |
|   If PcdMaximumLinkedListLength is not zero, and the number of nodes in the 
 | |
|   linked list containing Entry, including the Entry node, is greater than 
 | |
|   or equal to PcdMaximumLinkedListLength, then ASSERT().
 | |
| 
 | |
|   @param  Entry A pointer to a node in a linked list
 | |
| 
 | |
|   @return Entry
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| EFIAPI
 | |
| RemoveEntryList (
 | |
|   IN      CONST LIST_ENTRY      *Entry
 | |
|   )
 | |
| {
 | |
|   ASSERT (!IsListEmpty (Entry));
 | |
| 
 | |
|   Entry->ForwardLink->BackLink = Entry->BackLink;
 | |
|   Entry->BackLink->ForwardLink = Entry->ForwardLink;
 | |
|   return Entry->ForwardLink;
 | |
| }
 |